使用C ++ 11箭头decltype语句时,为什么boost::optional::operator*()
的行为与boost::optional::get()
不同?
这是我的代码:(此工作)
template<typename Fun, typename... Xs>
auto repeat_remove_optional(Fun f, std::string prompt, Xs&&... xs)
-> decltype(f(prompt, xs...).get())
{
auto x = f(prompt, xs...);
if (x) return *x;
prompt += "(Required!) ";
while (true) {
x = f(prompt, xs...);
if (x) return *x;
}
}
用例是一些提示用户使用字符串的函数,如果他们在输入过程中输入了escape,则返回boost::none
。
使用-> decltype(*f(prompt, xs...))
将无法编译,说rvalue reference to type 'bool' cannot bind to lvalue of type 'bool': if (x) return *x;
(在两个返回语句中都存在此错误)。
在我的代码中的其他地方,这两个函数的行为相同。为什么这会改变?
用法:
boost::optional<bool> prompt_yes_no(const std::string& message);
bool continue = repeat_remove_optional(prompt_yes_no,
"Are you sure you want to continue?"
答案 0 :(得分:4)
operator*
与value
具有等效的语义,但与get
的语义不同。
根据boost::optional
的{{3}},签名为:
T const& get() const;
T& get();
T const& operator *() const&;
T& operator *() &;
T&& operator *() &&;
T const& value() const&;
T& value() &;
T&& value() &&;
假设f(prompt, xs...)
返回某些boost::optional<T>
,decltype(*f(prompt, xs...))
为T&&
,而decltype(f(prompt, xs...).get())
为T&
。
auto x = f(prompt, xs...); // `x` has type `boost::optional<T>`.
if (x) {
return *x; // `*x` has type `T&`.
}
将bool
替换为T
,我们的错误为rvalue reference to type 'bool' cannot bind to lvalue of type 'bool'
在这种情况下,return *std::move(x)
会使表达式保持等效。
注意:return std::move(*x)
也可以使用,但细微的语义差异在于您将调用T& operator *() &
然后对结果{{1}执行std::move
而不是在T&
上执行std::move
,然后调用boost::optional<T>&
。后者更准确,因为表达式T&& operator *() &&
调用*f(prompt, xs...)
。
更新(感谢documentation感谢Praetorian):根据指定的返回类型,您现在将T&& operator*() &&
返回到包含的值T&&
位于函数堆栈上。最好x
结果类型:decay
。