C ++ std :: function找不到正确的重载 [英] C++ std::function cannot find correct overload

查看:210
本文介绍了C ++ std :: function找不到正确的重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下情况:

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

现在用

调用函数

  Set([](int a){
// ...
});

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

解决方案

我会建议这个解决方案。它应该与lambdas以及与函数对象一起工作。



框架: p>

  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具有一个参数< 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一个参数
f两个参数

演示: http://ideone.com/vtCDO



我采取了一些帮助从此主题的已接受答案:








解决Visual Studio 2010 b
$ b

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

//这与之前相同
template< typename Functor,size_t NArgs,typename ReturnType = void>
struct count_arg:std :: enable_if< function_traits< Functor> :: arity == NArgs,ReturnType>
{};

完整的演示(无可变模板):http://ideone.com/wbNj9



编辑

现在此代码支持任何返回类型。


Consider the following case:

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

Now calling the function with

Set([](int a) {
    //...
});

Gives "ambiguous call to overloaded function" error. I am using Visual Studio 2010. Is there a work around or another method to achieve something similar. I cannot use templates, because these functions are stored for later use because I cannot determine the number of parameters in that case. If you ask I can submit more details.

解决方案

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

Demo : http://ideone.com/vtCDO

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


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

A full demo (without variadic template) : http://ideone.com/wbNj9

EDIT
Now this code supports any return type.

这篇关于C ++ std :: function找不到正确的重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆