为什么这种对重载函数的调用不明确
Why is this call of overloaded function ambiguous?
为什么这个构造函数的调用是不明确的?
#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;
}
请注意类型转换。
有没有办法告诉编译器使用哪个构造函数重载?
这是标准的缺陷。请参阅 DR 2132:
请考虑以下事项:
#include <functional> void f(std::function<void()>) {} void f(std::function<void(int)>) {} int main() { f([]{}); f([](int){}); }
对 f 的调用是模棱两可的。显然是因为 从 lambda 转换为
std::function
序列是 相同。该标准指定函数对象给定std::function
"对于参数类型应为可调用 (20.8.11.2)ArgTypes
并返回类型R
."它并没有说如果这不是 在这种情况下,构造函数不是重载集的一部分。
尝试改用函数指针作为参数:
A(int f()) { f_ = f; }
A(float g()) { g_ = g; }
因为您要传递的内容与类型不匹配,所以我们进入转换序列以找到要使用的重载。 两个版本的函数都可以从返回 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) ...
等。。。 或者,您可以使用标记调度:
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); }
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; }
这里我们采用模棱两可的情况,并将积分分派给 int 重载,将非浮点分派给浮点重载。
它既可以转换为两者,但既不是浮点也不是积分的情况仍然模棱两可。 正如他们应该的那样。
sfina 条款可能很棘手。 如果不起作用,请替换:
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>{}>
以及其他CTOR类似。 例如,这可能适用于 MSVC。
由于 2015 年缺乏表达 sfinae,MSVC 可能需要完全进行标签调度。
相关文章:
- C++ 编译器错误:P1LinkedList.cpp:145:错误:重载的"to_string(int&)"调用不明确
- 为什么调用不明确的 ctor 时没有编译时错误?
- G++ 错误:重载的"abs(无符号 int)"的调用不明确
- 如果存在具有不同参数的继承成员,为什么对 C++ 结构函数的调用不明确?
- 错误:重载'stoi(nlohmann::basic_json<>::value_type&)'的调用不明确
- 构建 castalia 时出错:重载函数的调用不明确
- 错误:重载的"abs(double)"调用不明确
- 结构构造函数调用不明确
- 错误:对重载函数的调用不明确
- 对重载'swap(char&, char&)'的调用不明确
- 对可变模板函数的调用不明确
- C++ 编译错误:重载的"<function_name>(char*&)"调用不明确
- VS2010中具有list_of的调用不明确
- 为什么这个运算符=调用不明确
- 为什么对重载函数的调用不明确
- C++中重载运算符函数对构造函数的调用不明确
- 为什么这些重载函数调用不明确
- 重载write(int)的调用不明确
- 带有重载r值引用函数的调用不明确
- 传递0而不是1时,sfinae调用不明确