【问题标题】:C++1y auto function type deductionC++1y自动函数类型推导
【发布时间】:2014-06-10 22:41:12
【问题描述】:

考虑以下:

auto list = std::make_tuple(1, 2, 3, 4);

/// Work like a charm
template <class T>
auto test1(T &&brush) -> decltype(std::get<0>( std::forward<T>(brush) )) {
    return std::get<0>( std::forward<T>(brush) );
}


/// And now - C++14 feature
/// fail to compile - return value(temporary), instead of l-reference
template <class T>
auto test2(T &&brush) {
    return std::get<0>( std::forward<T>(brush) );
}

int main()
{
    auto &t1 = test1(list);
    auto &t2 = test2(list);        
}

http://coliru.stacked-crooked.com/a/816dea1a0ed3e9ee

gcc 和 clang 都抛出错误:

main.cpp:26:11: error: non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
    auto &t2 = test2(list);        
          ^    ~~~~~~~~~~~

它不应该像 decltype 那样工作吗?为什么不一样?


更新

如果是std::get,不就相当于这个吗? (我使用 gcc 4.8)

template <class T>
auto&& test2(T &&brush) {
    return std::get<0>( std::forward<T>(brush) );
}

【问题讨论】:

  • test1test2 返回类型为int,不能绑定到int&amp;。试试auto &amp;&amp; t1auto t1auto const &amp; t1
  • @BryanChen 为什么我不能引用 int 值?
  • @BryanChen test1 的返回类型是 int&amp;decltype 保留引用。这就是decltype(auto)auto 之间的区别。

标签: c++ auto c++14


【解决方案1】:

auto 只推导出对象类型,这意味着返回的对象的值类别不是返回类型的一部分。

使用auto占位符,通过模板参数推导规则推导出return语句的类型:

§ 7.1.6.4/7auto specificer[dcl.spec.auto]

如果占位符是自动类型说明符,则使用模板参数推导规则确定推导的类型。

另一方面,decltype(auto) 使用推论就像decltype()

§ 7.1.6.4/7auto specificer[dcl.spec.auto]

如果占位符是decltype(auto)类型说明符,则变量的声明类型或函数的返回类型应单独为占位符。为变量或返回类型推导的类型按照7.1.6.2 中的描述确定,就好像初始化程序是decltype 的操作数一样。

所以对于完美转发返回类型,这是您应该使用的。下面是它的外观:

template <class T>
decltype(auto) test2(T &&brush) {
    return std::get<0>(std::forward<T>(brush));
}

因此,返回类型将是一个右值/左值引用,具体取决于推导的brush 类型。

我在 Coliru 上测试了上面的代码,g++ 4.8 似乎还不能编译上面的代码,尽管使用 clang++ 编译得很好。

【讨论】:

  • 在别人之前回答那些 C++14 问题越来越难了.... C++ 有没有越过鲨鱼?
  • 我的 GCC 4.9 副本对您的代码没有任何问题,但使用尾随回车表示 auto 似乎有点过分。
  • +1 但你真的需要使用尾随返回类型来表示decltype(auto)吗?
  • 似乎没有尾随返回是可能的coliru.stacked-crooked.com/a/607a16b9d99afa71
  • @tower120 std::get 总是返回引用类型,因此auto&amp;&amp; 将执行引用折叠以将其推导出为正确的左值/右值引用。如果你使用decltype(auto),在这种情况下你会得到相同的结果,但在其他情况下它们是不等价的(比如返回非引用类型时,推导的类型将不是引用)。
【解决方案2】:

它不应该像使用 decltype 一样工作吗?为什么不同?

它应该像decltype 一样工作,但auto 在其他情况下与decltype 不完全一样,他们不想让auto 不一致。

相反,C++1y 为惯用的推导函数返回类型引入了新语法 decltype(auto)

【讨论】:

  • @tower120 Here 是 Scott Meyers 的博客文章。我似乎记得他有更深入的讨论。
猜你喜欢
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多