Why can't one compare a function pointer to a template function without explicit & on function name?

前端 未结 1 1319
灰色年华
灰色年华 2021-01-11 13:16

Consider the following code:

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

    bool test1 =          


        
相关标签:
1条回答
  • 2021-01-11 13:37

    This is a gcc bug, and you are in a corner case, in the C++ standard, Address of overloaded function §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 ]

    Do you see what is lacking in the list from (1.1) to (1.7)... built-in operators!

    If you declare an overload of operator == both gcc will not complain with the comparison, more than that you do not have to explicitly specialize the template function:

    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 and test3 compiles with gcc. test4 does not compile on gcc, but there are no overload resolution, you explicitly specialized the function. It really should compile. test5 does not compile as stated in the standard. In this case gcc produces the exact same error message as for test4. This is surely a gcc bug.

    0 讨论(0)
提交回复
热议问题