考虑以下情况:
void Set(const std::function<void(int)> &fn);
void Set(const std::function<void(int, int)> &fn);
现在用
调用该函数Set([](int a) {
//...
});
给出“对重载函数的模糊调用”错误。我正在使用Visual Studio 2010.是否有工作或其他方法来实现类似的东西。我不能使用模板,因为这些函数存储起来供以后使用,因为在这种情况下我无法确定参数的数量。如果你问我可以提交更多细节。
答案 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) {
//...
}));