1

テンプレート関数を含む次のコードがあります。 2番目のパラメータを列挙型としてこの関数を呼び出すと、テンプレートの特殊化が検出され、場合によってはそうではない場合もあります。C++で列挙型と一致するテンプレート関数のバリエーション

enumがどちらの場合も同じ列挙型(再定義がないなど)で、他のパラメータが正しい値を持っていることを確認したところ、-Winlineを使って1つのコンパイルが行われていました)何を見なければならない?

class A { 
public: 
    template <typename T> 
    int f(uint32_t id, T const& t, bool cond); 

    ... 
}; 

template <typename T> 
int A::f(uint32_t id, T const& t, bool cond) 
{ 
    ... 
} 

template <> 
inline int A::f<int>(uint32_t, int const& t, bool cond) 
{ 
    .... 
} 
+0

あなたはクラス内で特殊化を宣言せずにそのクラスの外側の関数テンプレートを特化することができていますか? –

+0

@Jeremiah Willcock-はい、これは合法です。あなたはそれを完全に専門化することだけが許されます。なぜ標準化委員会がこれを合法化することにしたのか分かりません。 – templatetypedef

+0

@templatetypedef:それは本当に奇妙です。私がコードに書いた修正を元に戻しましたか(特に専門分野の署名)? –

答えて

2

通常、テンプレート機能をオーバーロードする方法としてテンプレート特殊化を使用することはお勧めできません。テンプレートの特殊化は、関数のオーバーロードにはうまく対応せず、いつ選択するのかを決める非常に難解なルールがあります。一般に、関数テンプレートを特殊化するよりも、通常の関数オーバーロードを提供する方が良いと考えられます。この場合

、私はこのように見て、あなたのクラスを変更するお勧めする:

class A { 
public: 
    template <typename T> 
     int f(uint32_t id, T const& t, bool cond); 
    int f(uint32_t id, int t, bool cond); 
    ... 
}; 

それからちょうど過負荷の実装であるためにあなたのテンプレートの特殊化を変えます。 C++の関数オーバーロードが機能するため、関数の正しいバージョンがより正確に選択されます。

あなたの特定の質問に関しては、コードが常に過負荷を呼び出すとは限らないという理由は、C++は列挙型とタイプintを区別しているからです。 intと列挙型の間の変換方法は同じですが、intをキャッチするように設計されたオーバーロードは、列挙型を取得することは保証されません。列挙された大文字小文字を処理する関数を特にオーバーロードする方が良いでしょう。

+0

代替/回避策がありますが、それを推薦する根拠は基本的にFUDです。 –

+0

+1オーバーロードや専門分野の整数や列挙を混在させることは、言い表せないほど難しいことです。私の本では、それは悪い言葉で示されています: "未定義の行動"。 –

+0

@Mikael:「ねえ、スタンダードはこれが未定義の行動だとは言いません - それをしない」と言うのは、あまりにも些細なことです。 - 標準に従うコンパイラ "。私たちが話しているカテゴリを知っているか、失敗したコードに他の欠陥があるかどうかを知ることはいいでしょう(私が投稿したコードはGCCの問題を再現しませんでした)。 –

0

ない試みた答えが、コメントに収まるよりも多くを投稿したいが...

基本的に、これはGCC 3.4.6のために(列挙型は、int型の特化を一致しません)期待される挙動を示しています。どのコンパイラを使用していますか?実際に、エラーを生成する同様の完全なプログラムを提供できますか?

#include <iostream>                

struct A                   
{                    
    public:                  
    template <typename T>              
    void f(const T&) { std::cout << "general\n"; }        
};                    

template <>                  
void A::f<int>(const int&) { std::cout << "specialised\n"; }      

enum E1 { Zero, One, Two };              

enum E2 { Max = INT_MAX };              

int main()                  
{                    
    A a;                   
    a.f("abc");                 
    a.f(123);                 
    a.f(Zero);                 
    E1 e = Two;                 
    a.f(e);                  
    a.f(Max);                 
} 

出力:

general 
specialised 
general 
general 
general 
関連する問題