通过引用将std::experional::optional用作参数 < >我的C++编译器是代码> C++ 14 。我有一个函数,它接收一个自定义类的对象,该类封装了各种错误代码。此参数通过引用传递。自定义类对象有时会填充一个有效的错误值&有时它可以为空。我在C++14中发现了一个好看的新东西,就是。现在我尝试将其用于我的参数,因为它实际上是一个可选的参数

通过引用将std::experional::optional用作参数 < >我的C++编译器是代码> C++ 14 。我有一个函数,它接收一个自定义类的对象,该类封装了各种错误代码。此参数通过引用传递。自定义类对象有时会填充一个有效的错误值&有时它可以为空。我在C++14中发现了一个好看的新东西,就是。现在我尝试将其用于我的参数,因为它实际上是一个可选的参数,c++,c++14,C++,C++14,以下是我尝试使用的带有std::experimental::optional的函数签名: 但我收到以下编译器错误: 错误:对类型“std::experimental::optional”的非常量左值引用无法绑定到不相关类型“MyCustomErrorClass”MyFunction(某些参数,错误代码对象)的值; 我试着搜索了很多。大多数std::experimental::optional或std::optional使用示例都将其作为函数的返回值进行演示 我使用std::experiment

以下是我尝试使用的带有std::experimental::optional的函数签名:

但我收到以下编译器错误:

错误:对类型“std::experimental::optional”的非常量左值引用无法绑定到不相关类型“MyCustomErrorClass”MyFunction(某些参数,错误代码对象)的值;
我试着搜索了很多。大多数
std::experimental::optional
std::optional
使用示例都将其作为函数的返回值进行演示


我使用std::experimental::optional有什么问题?

你没有给你的函数一个可选的
MyCustomErrorClass
,而是给它一个非可选的
MyCustomErrorClass
。你通过引用给它,这意味着你可以尝试改变它,它会尝试改变传入的对象。但是你不能在一些实际上不是可选的东西上执行可变的
可选的
操作(如果你真的真的想,我想你可以…但是不好的事情会发生在做这种事情的人身上)。

你没有给你的函数一个可选的
MyCustomErrorClass
,您给它一个非可选的
MyCustomErrorClass
。你通过引用给它,这意味着你可以尝试改变它,它会尝试改变传入的对象。但是你不能对实际上不是可选的东西执行可变的
可选的
操作(好吧,如果你真的真的想,我想你可以…但是坏事情会发生在做这类事情的人身上)。

这不是关于
std::experiative::optional
;它是关于尝试将临时绑定到左值引用,这是不可能的

这是从
MyCustomErrorClass
隐式转换为
optional
的结果

解决您的问题的正确方法如下:

void f(long&);

int main()
{
   int x = 42;
   f(x);
}

// error: invalid initialization of non-const reference of type 'long int&' from an
//          rvalue of type 'long int'
可以在
int
long
之间进行隐式转换,但生成的临时值不能绑定到左值引用

相反,预构造
可选对象
并按名称传入。

optional<MyCustomErrorClass> opt_error_code_object = MyCustomErrorClass{};
MyFunction(some_param, opt_error_code_object);
可选opt_error_code_object=MyCustomErrorClass{};
MyFunction(某些参数、选项错误、代码、对象);

这不是关于
std::experimental::optional
;它是关于尝试将临时绑定到左值引用,这是不可能的

这是从
MyCustomErrorClass
隐式转换为
optional
的结果

解决您的问题的正确方法如下:

void f(long&);

int main()
{
   int x = 42;
   f(x);
}

// error: invalid initialization of non-const reference of type 'long int&' from an
//          rvalue of type 'long int'
可以在
int
long
之间进行隐式转换,但生成的临时值不能绑定到左值引用

相反,预构造
可选对象
并按名称传入。

optional<MyCustomErrorClass> opt_error_code_object = MyCustomErrorClass{};
MyFunction(some_param, opt_error_code_object);
可选opt_error_code_object=MyCustomErrorClass{};
MyFunction(某些参数、选项错误、代码、对象);

您不希望在此处通过引用获取可选项

对可选引用的引用与可选引用完全不同;第二个版本没有被选入C++17,因为它有令人困惑的语义,但它会更接近您想要的

可选项在其自身中存储其数据的副本。因此,对可选对象的引用是对包含对象副本的容器的引用

当您将错误对象传递给希望引用错误类型的可选项的函数时,它首先将错误对象复制到临时可选项中。然后它尝试将该临时绑定到(左值)引用;这是违法的。因此,您的代码无法编译

如果您通过创建一个非临时的可选对象或将临时对象强制转换为左值来“修复”它,您可能仍然得不到您想要的,因为函数现在与可选对象内的副本交互,而不是与原始错误对象交互

通常,当您通过引用传递对象时,需要将更改传播出去。但它们不会在可选的内部复制之外传播


解决方案是采用
MyCustomErrorClass*
——指针。这是可以为空的(类似于可选的),并且不存储副本。只需在呼叫站点添加一个
&
,当您不想通过它时,使用
nullptr

您不想在此处通过引用获取可选的

对可选引用的引用与可选引用完全不同;第二个版本没有被选入C++17,因为它有令人困惑的语义,但它会更接近您想要的

可选项在其自身中存储其数据的副本。因此,对可选对象的引用是对包含对象副本的容器的引用

当您将错误对象传递给希望引用错误类型的可选项的函数时,它首先将错误对象复制到临时可选项中。然后它尝试将该临时绑定到(左值)引用;这是违法的。因此,您的代码无法编译

如果您通过创建一个非临时的可选对象或将临时对象强制转换为左值来“修复”它,您可能仍然得不到您想要的,因为函数现在与可选对象内的副本交互,而不是与原始错误对象交互

通常,当您通过引用传递对象时,需要将更改传播出去。但它们不会在可选的内部复制之外传播

解决办法是
optional<MyCustomErrorClass> opt_error_code_object = MyCustomErrorClass{};
MyFunction(some_param, opt_error_code_object);