2017-02-28 11 views
10

Rozważmy następujący kod:Dlaczego nie można porównywać wskaźnika funkcji z funkcją szablonu bez jawnej nazwy funkcji?

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 
} 

Jeśli odkomentuj linię test2 i spróbuj skompilować kod z g ++, otrzymasz następujący błąd:

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 
        ^~~~~~~~~~~~~~~~~~ 

uzyskać ten wynik na g ++ 5.3.0 i 6.2.0. W tym samym czasie kompilacja z clang ++ 3.6.0 powiedzie się bez ostrzeżeń.

Który kompilator jest poprawny zgodnie ze Standardem tutaj - g ++, który daje błąd lub głos ++, co nie?

A jeśli g ++ ma rację, to dlaczego jest taka asymetria z normalnymi funkcjami w porównaniu z szablonowymi funkcjami dotyczącymi potrzeby jawnego adresu operatora?

+0

Mój zdrowy rozsądek mówi, że w tej sytuacji klang jest właściwy, ponieważ w pełni wyspecjalizowany szablon funkcji (lub raczej tworzenie) jest uważany za normalną funkcję i dlatego powinien działać w ten sposób. – DeiDei

+0

Czy to pozwala na wykonanie "void (* p) (int) = szablonemFunc ;", czy to też wymaga '& '? – TripeHound

+0

BTW, idiomatyczny sposób polega na użyciu '&'. – Jarod42

Odpowiedz

1

Jest to błąd gcc i jesteś w przypadku rogu, w standardzie C++, Adres funkcji przeciążonej §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 ]

Czy zobacz, czego brakuje na liście z (1.1) do (1.7) ... wbudowanych operatorów!

Jeśli zadeklarujesz przeciążenie operator == zarówno gcc nie będzie narzekać z porównania więcej niż to, że nie trzeba jawnie specjalizują funkcję szablonu:

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 

} 

test2 i test3 kompiluje z gcc. test4 nie kompiluje się na gcc, ale nie ma żadnej rozdzielczości przeciążenia, wyraźnie wyspecjalizowałeś tę funkcję. Naprawdę powinien się skompilować. test5 nie kompiluje się zgodnie z normą. W takim przypadku gcc generuje dokładnie ten sam komunikat o błędzie, co w przypadku test4. Z pewnością jest to błąd gcc.

Powiązane problemy