2017-02-28 11 views
10

は、次のコードを考えてみましょう:明示的な&on関数名なしで、関数ポインタをテンプレート関数と比較できないのはなぜですか?

void func(int) {} 
template<typename T> void templatedFunc(T) {} 
int main() 
{ 
    void (*p)(int) = func; 

    bool test1 = p==func; 
    //bool test2 = p==templatedFunc<int>; // compilation error 
    bool test3 = p==&templatedFunc<int>; // but this works 
} 

あなたがtest2行のコメントを解除し、G ++でコードをコンパイルしようとすると、次のエラー得られます:

test.cpp: In function ‘int main()’: 
test.cpp:8:21: error: assuming cast to type ‘void (*)(int)’ from overloaded function [-fpermissive] 
    bool test2 = p==templatedFunc<int>; // compilation error 
        ^~~~~~~~~~~~~~~~~~ 

を私はグラムで、この結果を得る++ 5.3.0および6.2.0。同時に、clang ++ 3.6.0によるコンパイルは警告なしで成功します。

ここで標準的なコンパイラは正しいですか?g ++はエラーを出しますか?clang ++はありませんか?

g ++が正しければ、明示的なアドレス演算子の必要性に関して、通常の関数とテンプレート関数のような非対称があるのはなぜですか?

+0

完全に特殊化された関数テンプレート(またはインスタンス化)が通常の関数とみなされ、そのように動作する必要があるため、私の常識はこの状況で正しいと言います。 – DeiDei

+0

'void(* p)(int)= templatedFunc ;'を実行できるかどうか、 '&'も必要ですか? – TripeHound

+0

ところで、慣習的なやり方は '&'を使うことです。 – Jarod42

答えて

1

これはgccのバグがあり、そしてあなたは、C++標準では、コーナーケースであるオーバーロードされた関数のアドレス§13.4([over.over]/1):

A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts. The function selected is the one whose type is identical to the function type of the target type required in the context. [ Note: That is, the class of which the function is a member is ignored when matching a pointer-to-member-function type. — end note ] The target can be:

(1.1) — an object or reference being initialized (8.5, 8.5.3, 8.5.4),

(1.2) — the left side of an assignment (5.18),

(1.3) — a parameter of a function (5.2.2),

(1.4) — a parameter of a user-defined operator (13.5),

(1.5) — the return value of a function, operator function, or conversion (6.6.3),

(1.6) — an explicit type conversion (5.2.3, 5.2.9, 5.4), or

(1.7) — a non-type template-parameter (14.3.2).

The overloaded function name can be preceded by the & operator. An overloaded function name shall not be used without arguments in contexts other than those listed. [ Note: Any redundant set of parentheses surrounding the overloaded function name is ignored (5.1). — end note ]

ですか(1.1)〜(1.7)のリストに欠けているものを見てください...組み込み演算子!

void func(int) {} 
template<class T> 
void templatedFunc(T) {} 
struct s{}; 
bool operator==(s, void(*)(int)){return false;} 
int main() 
{ 
    void (*p)(int) = templatedFunc; 

    bool test1 = p==func; 
    bool test2 = s{} == templatedFunc<int>; // no error - no overload resolution 
    bool test3 = s{} == templatedFunc; // no error - overload resolution 
    bool test4 = p == templatedFunc<int>; // gcc error, but not an error - 
             // no overload resolution 
//bool test5 = p == templatedFunc; // error - overload resolution not 
           // performed for built-int operators 

} 

test2test3 gccでコンパイル:あなたはoperator ==の過負荷を宣言した場合

両方gccが明示的にテンプレート関数を特化する必要はありません。それ以上に、比較して文句を言わないだろう。 test4はgccでコンパイルされませんが、オーバーロードの解決はなく、関数を明示的に特殊化しています。それは本当にコンパイルする必要があります。 test5は標準で述べたようにコンパイルされません。この場合、gccはtest4とまったく同じエラーメッセージを生成します。これは確かにgccのバグです。

関連する問題