C ++ std :: function找不到正确的重载 [英] C++ std::function cannot find correct overload
问题描述
请考虑以下情况:
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两个参数
我采取了一些帮助从此主题的已接受答案:
解决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屋!