C ++ std :: function找不到正确的重载

时间:2011-11-08 16:23:17

标签: c++ c++11 lambda

考虑以下情况:

void Set(const std::function<void(int)> &fn);
void Set(const std::function<void(int, int)> &fn);

现在用

调用该函数
Set([](int a) {
    //...
});

给出“对重载函数的模糊调用”错误。我正在使用Visual Studio 2010.是否有工作或其他方法来实现类似的东西。我不能使用模板,因为这些函数存储起来供以后使用,因为在这种情况下我无法确定参数的数量。如果你问我可以提交更多细节。

3 个答案:

答案 0 :(得分:12)

我会建议这个解决方案。它应该与lambdas以及函数对象一起使用。它可以扩展为使其适用于函数指针(只需通过底部提供的链接)

<强>框架:

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>
{};

用法:

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;
}

输出:

f with one argument
f with two arguments

我从这个主题的接受答案中得到了一些帮助:


解决Visual Studio 2010

由于Microsoft Visual Studio 2010不支持可变参数模板,因此框架部分可以实现为:

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>
{};

修改
现在这段代码支持任何返回类型。

答案 1 :(得分:1)

我建议:

  void Set(void(*f)(int, int))
  { 
      std::function<void(int,int)> wrap(f);
      // ...
  }

  void Set(void(*f)(int))
  { 
      std::function<void(int)> wrap(f);
      // ...
  }

答案 2 :(得分:1)

您可以手动指定类型:

Set(std::function<void(int)>([](int a) {
    //...
}));