web-dev-qa-db-ja.com

関数テンプレート特化フォーマット

次の関数テンプレートの2番目の括弧<>の理由は何ですか。

_template<> void doh::operator()<>(int i)
_

これは SO質問 で発生し、operator()の後に角かっこがないことが示唆されましたが、説明が見つかりませんでした。

次の形式の型特殊化(完全な特殊化)である場合、その意味を理解しています。

_template< typename A > struct AA {};
template<> struct AA<int> {};         // hope this is correct, specialize for int
_

ただし、関数テンプレートの場合:

_template< typename A > void f( A );
template< typename A > void f( A* ); // overload of the above for pointers
template<> void f<int>(int);         // full specialization for int
_

これはこのシナリオにどこに適合しますか?:

_template<> void doh::operator()<>(bool b) {}
_

動作しているように見え、警告/エラーを出さないコードの例(gcc 3.3.3を使用):

_#include <iostream>
using namespace std;

struct doh
{
    void operator()(bool b)
    {
        cout << "operator()(bool b)" << endl;
    }

    template< typename T > void operator()(T t)
    {
        cout << "template <typename T> void operator()(T t)" << endl;
    }
};
// note can't specialize inline, have to declare outside of the class body
template<> void doh::operator()(int i)
{
    cout << "template <> void operator()(int i)" << endl;
}
template<> void doh::operator()(bool b)
{
    cout << "template <> void operator()(bool b)" << endl;
}

int main()
{
    doh d;
    int i;
    bool b;
    d(b);
    d(i);
}
_

出力:

_operator()(bool b)
template <> void operator()(int i)
_
30
stefanB

調べたところ、14.5.2/2で指定されていることがわかりました。

ローカルクラスはメンバーテンプレートを持っていません。アクセス制御規則(11節)は、メンバーテンプレート名に適用されます。デストラクタはメンバーテンプレートではありません。特定の名前とタイプの通常の(非テンプレート)メンバー関数と、同じタイプの特殊化を生成するために使用できる同じ名前のメンバー関数テンプレートは、どちらもクラスで宣言できます。両方が存在する場合、その名前とタイプの使用は、明示的なテンプレート引数リストが提供されない限り、非テンプレートメンバーを参照します。

そして、それは例を提供します:

_template <class T> struct A {
    void f(int);
    template <class T2> void f(T2);
};

template <> void A<int>::f(int) { } // non-template member
template <> template <> void A<int>::f<>(int) { } // template member

int main()
{
    A<char> ac;
    ac.f(1); //non-template
    ac.f(’c’); //template
    ac.f<>(1); //template
}
_

標準用語では、specializationは明示的な特殊化を使用して記述した関数と、インスタンス化を使用して生成された関数を指します。この場合、生成された特殊化を使用する必要があります。 specializationは、明示的に特殊化されたテンプレートを使用して作成する関数を参照するだけでなく、そのテンプレートが頻繁に使用されるだけです。

結論:GCCはそれを誤解しています。私もコードをテストしたコモーはそれを正しく理解し、診断を発行します:

_"ComeauTest.c"_、16行目:エラー:"void doh::operator()(bool)"は、明示的に特殊化できるエンティティではありませんtemplate<> void doh::operator()(bool i)

同じ名前を参照していないため、intboolのみ)のテンプレートの特殊化について不平を言わないことに注意してくださいand type :特殊化が持つ関数タイプはvoid(int)であり、これは非テンプレートメンバー関数の関数タイプであるvoid(bool)とは異なります。