web-dev-qa-db-ja.com

テンプレートクラスでテンプレート関数を明示的に特殊化するためのC ++構文?

VC9(Microsoft Visual C++ 2008 SP1)では機能するが、GCC 4.2(Mac)では機能しないコードがあります。

struct tag {};

template< typename T >
struct C
{   
    template< typename Tag >
    void f( T );                 // declaration only

    template<>
    inline void f< tag >( T ) {} // ERROR: explicit specialization in
};                               // non-namespace scope 'structC<T>'

GCCが明示的な特殊化をクラスの外に移動することを望んでいることを理解していますが、構文を理解できません。何か案は?

// the following is not correct syntax, what is?
template< typename T >
template<>
inline void C< T >::f< tag >( T ) {}
43
jwfearn

包含クラスを明示的に特化しないと、メンバー関数を特化できません。
ただし、できることは、部分的に特殊化されたタイプのメンバー関数への呼び出しを転送することです:

template<class T, class Tag>
struct helper {
    static void f(T);   
};

template<class T>
struct helper<T, tag1> {
    static void f(T) {}
};

template<class T>
struct C {
    // ...
    template<class Tag>
    void foo(T t) {
        helper<T, Tag>::f(t);
    }
};
36
Georg Fritzsche

GCCは明確にここにあります。 MSVCには、クラス内の特殊化を可能にする非標準の拡張機能があります。しかし、標準は言う:

14.7.3.2:
2。明示的な特殊化は、テンプレートがメンバーである名前空間、またはメンバーテンプレートの場合は、包含クラスまたは包含クラステンプレートがメンバーである名前空間で宣言する必要があります。メンバー関数、メンバークラス、またはクラステンプレートの静的データメンバーの明示的な特殊化は、クラステンプレートがメンバーとなっている名前空間で宣言する必要があります。

さらに、関数を部分的に特化することはできません。 (あなたのケースの詳細についてはわかりませんが、それが最後の一撃になります。)

あなたcouldこれを行う:

#include <iostream>

struct true_type {};
struct false_type {};

template <typename T, typename U>
struct is_same : false_type
{
    static const bool value = false;
};

template <typename T>
struct is_same<T, T> : true_type
{
    static const bool value = true;
};

struct tag1 {};
struct tag2 {};

template< typename T >
struct C
{
    typedef T t_type;

    template< typename Tag >
    void foo( t_type pX)
    {
        foo_detail( pX, is_same<Tag, tag1>() );
    }

private:
    void foo_detail( t_type, const true_type& )
    {
        std::cout << "In tag1 version." << std::endl;
    }
    void foo_detail( t_type, const false_type& )
    {
        std::cout << "In not tag1 version." << std::endl;
    }
};

int main(void)
{
    C<int> c;
    c.foo<tag1>(int());
    c.foo<tag2>(int());
    c.foo<double>(int());
}

これはやや醜いですが。

10
GManNickG

私はこれがあなたを満足させないかもしれないことを知っていますが、あなたが明示的に専門化されていない構造に囲まれた専門化を持っていないかもしれないとは思いません。

template<>
template<>
inline void C< tag1 >::foo< tag2 >( t_type ) {}
1
ephemient

これを試して:

template <> template<typename T> inline void C<T> :: foo<tag2>(T) {}
0