C++ 为什么重载函数的调用不明确?

C++ 为什么重载函数的调用不明确?,c++,c++11,lambda,stl,C++,C++11,Lambda,Stl,为什么这个构造函数调用不明确 #include <functional> class A { std::function<int(void)> f_; std::function<float(void)> g_; public: A(std::function<int(void)> f) { f_ = f; } A(std::function<float(void)> g) { g_ = g; }

为什么这个构造函数调用不明确

#include <functional>

class A {
    std::function<int(void)> f_;
    std::function<float(void)> g_;
public:
    A(std::function<int(void)> f) { f_ = f; }
    A(std::function<float(void)> g) { g_ = g; }
    ~A() {}
};

int main()
{
    A a([](){ return (int)1; });
    return 0;
}
#包括
甲级{
std::函数f;
std::函数g;
公众:
A(std::函数f){f_uz=f;}
A(std::function g){g_uu=g;}
~A(){}
};
int main()
{
A([]){return(int)1;});
返回0;
}
注意打字


有没有办法告诉编译器要使用哪个构造函数重载?

因为您传递的内容与类型不匹配,所以我们输入转换序列以查找要使用的重载。函数的两个版本都可以从返回int的lambda对象隐式创建。因此编译器无法决定选择创建哪个;虽然它看起来直观明了,但是C++中的规则不允许。 编辑:

袖口一笔勾销,但我认为这可以达到目的:

template < typename Fun >
typename std::enable_if<std::is_same<typename std::result_of<Fun()>::type, int>::value>::type f(Fun f) ...


template < typename Fun >
typename std::enable_if<std::is_same<typename std::result_of<Fun()>::type, double>::value>::type f(Fun f) ...
模板
typename std::enable_if::type f(Fun f)。。。
模板
typename std::enable_if::type f(Fun f)。。。
等等。。。或者您可以使用标记分派:

template < typename Fun, typename Tag >
struct caller;

template < typename T > tag {};

template < typename Fun >
struct caller<Fun, tag<int>> { static void call(Fun f) { f(); } };

// etc...

template < typename Fun >
void f(Fun fun) { caller<Fun, typename std::result_of<Fun()>>::call(fun); }
模板
结构调用方;
模板标记{};
模板
结构调用方{static void call(Fun f){f();}};
//等等。。。
模板
void f(Fun){caller::call(Fun);}

这是标准中的一个缺陷。见:

考虑以下几点:

#include <functional>

void f(std::function<void()>) {}
void f(std::function<void(int)>) {}

int main() {
  f([]{});
  f([](int){});
}
模板
A(F&&F):A(std::function(std::forward(F)){
模板
A(F&&F):A(std::function(std::forward(F)){
A(std::函数f){f_uz=f;}
A(std::function g){g_uu=g;}
在这里,我们使用不明确的情况,将整数的情况分派给int重载,将非浮点的情况分派给浮点的情况

如果它可以同时转换为两种类型,但既不是浮点型也不是整数型,则仍然不明确。他们应该这样做

sfina条款可能很棘手。如果不起作用,则更换:

  std::enable_if_t<std::is_convertible<R,float>{}&&(!std::is_convertible<R,int>{}||std::is_floating_point<R>{}, int> =0
std::在t=0时启用

class=std::启用
其他行业也类似。例如,这可能在MSVC中起作用


由于2015年缺少sfinae表达式,msvc可能需要完全标记调度。

但当我为函数模板使用另一个返回类型(例如指针类型)时,它会起作用:你想做什么?也许从那开始在这里会更好。例如,您可以将
[]()->int
[]()->float
存储到
函数中。然后在调用它之后,您可以通过
boost::apply_visitor(a.f(),[](auto x){…})
除了函数之外,还有其他包装器来处理lambda吗?一个没有那么贪婪的模板构造器?你可以用SFINAE创建一个。在lambdas上使用可能需要一些基本之外的元编程技能,特别是如果您还想接受自由函数和成员的话。不幸的是,它们似乎和lambda的捕获功能不兼容。我的元编程技能还不足以理解这件奇怪的事情。正如我在另一篇评论中所写,函数指针参数与lambda的捕获功能不兼容。出于某种原因,在使用函数指针和捕获变量时,我得到一个
无匹配函数用于调用…
错误。DR2132是关于从无法使用指定签名调用的函数对象中删除隐式转换序列。在OP的情况下,lambda可以为两个签名调用(
int()
float()
)。
template<class F,
  class R=std::result_of_t<F&()>,
  std::enable_if_t<std::is_convertible<R,int>{}&&(!std::is_convertible<R,float>{}||std::is_integral<R>{}),int> =0
>
A(F&&f):A(std::function<int()>(std::forward<F>(f))){}
template<class F,
  class R=std::result_of_t<F&()>,
  std::enable_if_t<std::is_convertible<R,float>{}&&(!std::is_convertible<R,int>{}||std::is_floating_point<R>{}, int> =0
>
A(F&&f):A(std::function<float()>(std::forward<F>(f))){}
A(std::function<int()> f) { f_ = f; }
A(std::function<float()> g) { g_ = g; }
  std::enable_if_t<std::is_convertible<R,float>{}&&(!std::is_convertible<R,int>{}||std::is_floating_point<R>{}, int> =0
  class=std::enable_if_t<std::is_convertible<R,float>{}&&(!std::is_convertible<R,int>{}||std::is_floating_point<R>{}>