Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用std::function时,选择自动返回类型而不是构造函数的调用运算符_C++_C++14_Std Function_Function Object_Return Type Deduction - Fatal编程技术网

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())
  • 使用
    -std=c++1z
    编译(谢谢@bolov)

也许有一些明显的东西我在这里错过了。。。这个代码有什么问题吗?这是一个bug吗?

您正在初始化
x
。由于以下原因,
X
是一种棘手的类型:

  • 它可以由任何可调用对象构造,这些对象可以用双参数调用。其返回类型可转换为双精度

  • 它本身是一个可调用对象,可以用双参数调用。但是返回类型需要推导

  • 有一个编译器为
    X
    生成的复制构造函数

  • 我希望,这里的模糊性开始变得明显起来。有必要解决过载问题

    当您删除第一个c'tor时,它会以一种明显的方式消除歧义。有趣的例子是函数调用操作符

    您可以看到,
    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
    是否应被取消资格。