C++ std::function cannot find correct overload

后端 未结 3 639
闹比i
闹比i 2021-02-07 12:19

Consider the following case:

void Set(const std::function &fn);
void Set(const std::function &fn);
相关标签:
3条回答
  • 2021-02-07 12:38

    I suggest:

      void Set(void(*f)(int, int))
      { 
          std::function<void(int,int)> wrap(f);
          // ...
      }
    
      void Set(void(*f)(int))
      { 
          std::function<void(int)> wrap(f);
          // ...
      }
    
    0 讨论(0)
  • 2021-02-07 12:53

    You can manually specify the type:

    Set(std::function<void(int)>([](int a) {
        //...
    }));
    
    0 讨论(0)
  • 2021-02-07 12:55

    I would suggest this solution. It should work with lambdas as well as with function-objects. It can be extended to make it work for function pointer as well (just go through the link provided at the bottom)

    Framework:

    template <typename T>
    struct function_traits : public function_traits<decltype(&T::operator())>
    {};
    
    template <typename ClassType, typename ReturnType, typename... Args>
    struct function_traits<ReturnType(ClassType::*)(Args...) const>
    {
        enum { arity = sizeof...(Args) };
    };
    
    template<typename Functor, size_t NArgs>
    struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, int>
    {};
    

    Usage:

    template<typename Functor>
    typename count_arg<Functor, 1>::type Set(Functor f) 
    {
        std::function<void(int)> fn = f;
        std::cout << "f with one argument" << std::endl;
    }
    
    template<typename Functor>
    typename count_arg<Functor, 2>::type Set(Functor f)
    {
        std::function<void(int, int)> fn = f;
        std::cout << "f with two arguments" << std::endl;
    }
    
    int main() {
            Set([](int a){});
            Set([](int a, int b){});
            return 0;
    }
    

    Output:

    f with one argument
    f with two arguments
    

    I took some help from the accepted answer of this topic:

    • Is it possible to figure out the parameter type and return type of a lambda?

    Work around for Visual Studio 2010

    Since Microsoft Visual Studio 2010 doesn't support variadic templates, then the framework-part can be implemented as:

    template <typename T>
    struct function_traits : public function_traits<decltype(&T::operator())>
    {};
    
    template <typename C, typename R, typename T0>
    struct function_traits<R(C::*)(T0) const> { enum { arity = 1 }; };
    
    template <typename C, typename R, typename T0, typename T1>
    struct function_traits<R(C::*)(T0,T1) const> { enum { arity = 2 }; };
    
    template <typename C, typename R, typename T0, typename T1, typename T2>
    struct function_traits<R(C::*)(T0,T1,T2) const> { enum { arity = 3 }; };
    
    //this is same as before 
    template<typename Functor, size_t NArgs, typename ReturnType=void>
    struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, ReturnType>
    {};
    

    EDIT
    Now this code supports any return type.

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