我的C ++编译器是C++ 14
。我有一个函数,它接入一个自定义类的对象,它封装了各种错误代码。此参数通过引用传递。自定义类对象有时会填充有效的错误值&有时它可能是空的。我在C ++ 14中找到了一个很好看的新东西std::experimental::optional。现在我尝试将此用作我的参数,因为它实际上是optional
参数。
以下是我正在尝试使用std :: experimental :: optional的函数签名:
MyFunction(some param, std::experimental::optional<MyCustomErrorClass> & error_code) {
//some logic
//sometimes error_code is populated & sometimes not populated
}
以下是我致电MyFunction
的方式:
MyCustomErrorClass error_code_object;
MyFunction(some_param, error_code_object);
但是我收到以下编译错误:
error: non-const lvalue reference to type 'std::experimental::optional< MyCustomErrorClass>' cannot bind to a value of unrelated type 'MyCustomErrorClass' MyFunction(some_param, error_code_object);
我试着搜索了很多。大多数std::experimental::optional
或std::optional
用法示例都将其演示为函数的返回值。
我对std :: experimental :: optional的使用有什么问题?
答案 0 :(得分:2)
这不是std::experimental::optional
;它是关于尝试将临时绑定到左值引用,这是不可能的。
该临时性是从MyCustomErrorClass
到optional<MyCustomErrorClass>
隐式转换的结果。
问题的正确MCVE如下:
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
对象并按名称传递。
optional<MyCustomErrorClass> opt_error_code_object = MyCustomErrorClass{};
MyFunction(some_param, opt_error_code_object);
答案 1 :(得分:2)
您不想在此引用可选项。
对可选项的引用是一种非常不同的可选引用的野兽;第二个没有被投票到C ++ 17,因为它有令人困惑的语义,但它会更接近你想要的。
可选的存储其数据的副本。因此,对可选项的引用是对包含对象的副本的容器的引用。
当您将错误对象传递给期望引用错误类型的可选项的函数时,它首先将错误对象复制到临时可选项中。然后它尝试将该临时值绑定到(左值)引用;这是非法的。所以你的代码无法编译。
如果你&#34;修复&#34;它通过创建一个非临时的可选项,或者将临时值转换为左值,你可能仍然得不到你想要的,因为该函数现在与可选内的副本交互,而不是原始的错误对象。
通常,当您通过引用传递对象时,您希望更改为propogate out。但他们不会在选项内的副本之外传播。
解决方案是采用MyCustomErrorClass*
- 一个指针。这是可空的(如可选),并不存储副本。只需在调用网站上添加&
,并在您不想传递时使用nullptr
。
答案 2 :(得分:1)
您没有为您的功能提供可选的MyCustomErrorClass
,而是为其提供了非可选的MyCustomErrorClass
。并且您通过引用提供它,这意味着您可以尝试改变它并且它会尝试改变传入的对象。但是您无法对某些内容执行可变optional<T>
操作实际上并不是optional<T>
(好吧,我想你可以,如果你真的,真的想......但是那些做过那种事的人会发生不好的事情)。