2017-10-02 2 views
0

Converterクラスは、文字列を別の型に変換するように設計されています。したがって、ターゲットも文字列であれば、元の値のコピーを返すだけです。クラス外の特殊化テンプレートメソッドを宣言するにはどうすればよいですか?

作業コードは、このようなものです:

template<typename C> 
class Converter { 
public: 
    template<typename T> 
    static T To(const std::wstring& obj); 

    template<> 
    static std::wstring To(const std::wstring& obj) { 
     return obj; 
    } 
}; 

template<typename C> 
template<typename T> 
T Converter<C>::To(const std::wstring& obj) { 
    // Conversion 
    return T(); 
} 

(VC++ 2015上で動作アップデート3)

私はこのようなクラス宣言の外に専門の方法を移動しようとした:

template<typename C> 
template<> 
std::wstring Converter<C>::To<std::wstring>(const std::wstring& obj) { 
    return obj; 
} 

いくつかのコンパイルエラーがあります。

エラーC3212「のコンバーター:: TO」: テンプレートメンバーの明示的な特殊化は

エラーC2768「のコンバーター::」に明示的な特殊のメンバーである必要があります。明示的なテンプレートの不正使用 引数

+1

あなたの「作業コード」[うまくいかない](http://coliru.stacked-crooked.com/a/852632a3c4a83d69)。 – cdhowie

+3

私はどちらも標準によると実際に違法だと思うが、何らかの理由でMSVCが最初のことを許してしまう。どちらもGCCの下では動作しません。外側のテンプレートを特化せずに内側のテンプレートを明示的に特殊化することはできないようです。 –

+0

@cdhowieはVC++ 2015で動作します。 – user1633272

答えて

1

親指のルール:

は、特化した関数オーバーロードを優先します!あなたのケースの使用過多とsfinaeで

#include <type_traits> 
#include <string> 

template<typename C> 
class Converter { 
public: 
    template<typename T, typename std::enable_if<!std::is_same<T, std::wstring>::value>::type* = nullptr > 
    static T To(const std::wstring& obj) { 

    } 

    template<typename T, typename std::enable_if<std::is_same<T, std::wstring>::value>::type* = nullptr > 
    static std::wstring To(const std::wstring& obj) { 

    } 
}; 

[live demo]

+0

これらの2つのメソッドをクラス宣言の外側に宣言する方法はありますか? – user1633272

+0

@ user1633272あなたは –

+0

@ user1633272に行くことができます。 'std :: is_same'の中で' typename Converter :: StringType'を使用できませんか? –

1

は何をしようとしているが、明示的に禁止されています:

[temp.expl.spec]/16を明示的な特殊宣言ではクラステンプレートのメンバーまたはメンバーのTEMPLのために宣言は、その囲むクラステンプレートが明示的に特殊化されていない場合でも明示的にクラスメンバテンプレートを特化してはならないことを除いて、 [emphasis mine] ... [例:

template <class T1> class A { 
    template<class T2> class B { 
    template<class T3> void mf1(T3); 
    void mf2(); 
    }; 
}; 
template <> template <class X> 
    class A<int>::B { 
    template <class T> void mf1(T); 
    }; 
template <> template <> template<class T> 
    void A<int>::B<double>::mf1(T t) { } 

template <class Y> template <> 
    void A<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized but 
            // its enclosing class template A is not 

から端例]

2

あなたがタグを使用する場合がありますが代わりにディスパッチ:

template <typename> struct Tag{}; 

template<typename C> 
class Converter { 

    template<typename T> 
    static T To(const std::wstring& obj, Tag<T>); 

    static std::wstring To(const std::wstring& obj, Tag<std::wstring>); 

public: 
    template<typename T> 
    static T To(const std::wstring& obj) { return To(obj, Tag<T>{}); } 
}; 

そして

template<typename C> 
template<typename T> 
T Converter<C>::To(const std::wstring& obj, Tag<T>) { 
    // Conversion 
    return T(); 
} 

template<typename C> 
std::wstring Converter<C>::To(const std::wstring& obj, Tag<std::wstring>) { 
    return obj; 
} 
関連する問題