std::optional<T> 和对 T 进行非常量引用的函数
std::optional<T> and functions taking a non-const reference to T
假设我有一个函数
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;
你可以这样做:
if (!my_var) { my_var.emplace(); }
set_value(*my_var);
但更好的方法是简单地将 set_value
的签名更改为:
MyType set_value();
这样你就可以写:
my_var = set_value();
Input/Output 参数糟透了。
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
: 对于如此喜爱的可选 "hello world" 他们给了它唯一的内容,任何相信它的人都不会出现段错误,但有一个正确的程序。
假设我有一个函数
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;
你可以这样做:
if (!my_var) { my_var.emplace(); }
set_value(*my_var);
但更好的方法是简单地将 set_value
的签名更改为:
MyType set_value();
这样你就可以写:
my_var = set_value();
Input/Output 参数糟透了。
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
: 对于如此喜爱的可选 "hello world" 他们给了它唯一的内容,任何相信它的人都不会出现段错误,但有一个正确的程序。