std :: optional <t>和对T采用非const引用的函数

时间:2016-03-10 16:20:17

标签: c++ c++11 optional c++17

假设我有一个功能

void set_value(MyType& x);

我希望用类型

的变量来调用它
std::experimental::optional<MyType> myvar

我不能简单地致电set_value(*myvar),因为myvar可能没有值。在所有情况下,如何安全地确保set_value() myvar的结果?

我想避免写作:

decltype(my_var)::value_type tmp;
set_value(tmp);
my_var = tmp;

2 个答案:

答案 0 :(得分:3)

你可以这样做:

if (!my_var) { my_var.emplace(); }
set_value(*my_var);

但更好的方法是只需将set_value的签名更改为:

MyType set_value();

所以你可以写完:

my_var = set_value();

输入/输出参数很糟糕。

答案 1 :(得分:2)

template<class F, class T>
decltype(auto) set_optional( F&& f, std::experimental::optional<T>& o ) {
  if (!o) o.emplace();
  return std::forward<F>(f)(*o);
}

现在你可以:

set_optional( set_value, myvar );

它有效。

但请注意,引用MyType的函数需要输入和输出参数。仅返回输出参数。许多人将其重用于仅输出参数。这会导致类似上面遇到的问题以及不必要的默认构造。

set_value(*myvar);

您可以内联执行此操作:

if (!myvar) myvar.emplace();
set_value(*myvar);

如果我们构造它,如果为空,则使用它。

或者,不同的重构(我觉得很好):

template<class T, class...Args>
T& emplace_or( std::experimental::optional<T>& o, Args&&...args ) {
  if (!o) o.emplace(std::forward<Args>(args)...);
  return *o;
}

然后:

set_value(emplace_or(myvar));

或者最后一个选项:

set_value(void(!myvar?myvar.emplace(),void(),3:16),*myvar)

void(),3:16:对于可选的如此喜爱的“你好世界”,他们给了它们唯一的内容,任何相信它都参与其中的内容不应该是段错误的,而是要有正确的程序。