C++ 使用std::function时,选择自动返回类型而不是构造函数的调用运算符
以下代码段:C++ 使用std::function时,选择自动返回类型而不是构造函数的调用运算符,c++,c++14,std-function,function-object,return-type-deduction,C++,C++14,Std Function,Function Object,Return Type Deduction,以下代码段: #include <functional> struct X { X(std::function<double(double)> fn); // (1) X(double, double); // (2) template <class T> auto operator()(T const& t) const { // (3) return t.fo
#include <functional>
struct X {
X(std::function<double(double)> fn); // (1)
X(double, double); // (2)
template <class T>
auto operator()(T const& t) const { // (3)
return t.foo();
}
};
int main() {
double a, b;
auto x = X(a, b);
return 0;
}
#包括
结构X{
X(标准::函数fn);/(1)
X(双,双);/(2)
模板
自动运算符()
返回t.foo();
}
};
int main(){
双a,b;
自动x=x(a,b);
返回0;
}
…使用OSX和上测试的-std=c++14
-时,clang
(4.0.1)和g++
(6.3,7.2)无法编译
但如果满足以下条件,则编译不会出现问题:
- 我删除构造函数
李>(1)
- 或者我在
中将返回类型设置为具体类型(例如(3)
)李>double
- 或者如果我在
中使用尾部返回类型((3)
)李>->decltype(t.foo())
- 使用
编译(谢谢@bolov)-std=c++1z
也许有一些明显的东西我在这里错过了。。。这个代码有什么问题吗?这是一个bug吗?您正在初始化
x
。由于以下原因,X
是一种棘手的类型:
X
生成的复制构造函数std::function
只能从传递给它的可调用函数构造(模板化的c'tor将只参与重载解析),前提是参数之间以及返回类型之间的转换是可能的。这一切都是在未赋值的上下文中完成的,因此模板化的函数调用操作符没有使用odr,因此没有实例化
当返回类型是占位符类型时,std::function
c'tor无法轻松解析是否应该构造它。在重载解析过程中编译失败,即使编译成功,也会选择X
的副本
正如@VTT在评论中所建议的,将接受
std::function
的任务标记为显式也将解决歧义。所有这些都是因为编译器根本不必对隐式转换序列进行排序。C++1z标志没有错误:但说真的,wtf,用C++14
做什么?我猜auto x=x{a,b}代码>是另一个成功编译的变体吗?@TobySpeight不适合我,它失败了,并出现了相同的错误。@bolov:在C++17中,规则有变化(有保证副本省略),代码相当于X(a,b)代码>;在C++11中,还不支持将auto
推断为返回类型。如果添加代码行autoy=x
,在C++17中也会发生同样的情况@bolov-有两个可行的c'tor来构造对象。除非有人被明确取消资格。将函数标记为explicit
将使它工作。@bolov如果你写x1(a,b),它会更清晰;x2=x1
,问题是从x1
@StoryTeller构建x2
,谢谢,我确实理解问题的根源,但我不理解它最终会变成这样-复制构造函数在这里不是更好的匹配吗?在这种情况下,为什么要实例化std::function(X)
的构造函数?@Holt-是的。但问题是重载解析仍然必须发生,占位符类型会干扰检查std::function
是否应被取消资格。