Expression SFINAE to overload on type of passed function pointer

后端 未结 2 463
一生所求
一生所求 2021-01-18 06:47

In this example a function is passed to an implicitly instantiated function template.

// Function that will be passed as argument
int foo() { return 0; }

//         


        
2条回答
  •  时光说笑
    2021-01-18 07:31

    As has been mentioned before, SFINAE doesn't work because the names of overloaded functions have no definite type in C++, therefore template parameter substitution doesn't even happen at this stage.

    However, in your example, the problem is arguably not that you have too many overloads of "foo", but too few overloads of "call". Just provide both the templates with typename F and the ones that expect a function pointer. The compiler will now be able to do the right thing depending on context:

    #include 
    
    // Functions
    int foo() { return 0; }
    
    int foo(int) { return 1; }
    
    // Function object
    struct Foo
    {
        int operator()() const { return 2; }
        int operator()(int) const { return 3; }
    };
    
    // Higher-order functions / templates
    template
    int call(F f) {
        return f();
    }
    
    int call(int (*f)()) {
        return f();
    }
    
    template
    int call(F f, A a) {
        return f(a);
    }
    
    template
    int call(int (*f)(A), A a) {
        return f(a);
    }
    
    int main()
    {
        int a = call(foo)
          , b = call(foo, 0)
          , c = call(Foo())
          , d = call(Foo(), 0);
        std::cout << a << ',' << b << ',' << c << ',' << d << '\n';  // 0,1,2,3
    }
    

    The call overloads can be made more generic by adding return type deduction. In C++11, this is possible even with function objects by using decltype rsp. result_of. For brevity, I will post only the new function signatures, as the bodies don't need to be changed in this case:

    template
    auto call(F f) -> decltype(f());
    
    template
    R call(R (*f)());
    
    template
    auto call(F f, A a) -> decltype(f(a));
    
    template
    R call(R (*f)(A), A a);
    

提交回复
热议问题