使用` - >推断返回类型decltype`

时间:2015-12-22 22:54:52

标签: c++ c++11 boost

使用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?"

1 个答案:

答案 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