【问题标题】:std::tuple::get returning const Type&&std::tuple::get 返回 const Type&&
【发布时间】:2017-03-31 02:47:51
【问题描述】:

我刚刚在 cppreference http://en.cppreference.com/w/cpp/utility/tuple/get 上为 std::tuple::get 阅读了 C++17 的更新接口,新的重载从 get<>() 函数返回 const Type&&。为什么要返回 const Type&& 而不是普通的 const Type&?你不能从任何一种类型的实例中移动..

这些是我所指的函数声明供参考

template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t);

template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >const&&
get( const tuple<Types...>&& t );

【问题讨论】:

  • 这样你就可以完美地转发文字抛出整个调用double d = std::get&lt;double&gt;(std::make_tuple(1, "Foo", 3.14));
  • @HenriMenke 我想他们问的是返回,而不是转发。

标签: c++ tuples c++14 rvalue-reference c++17


【解决方案1】:

谷歌搜索出现了Issue 2485,它指出了这样一个缺陷:

#include <functional>
#include <string>
#include <tuple>

using namespace std; 

string str1() { return "one"; }
const string str2() { return "two"; }
tuple<string> tup3() { return make_tuple("three"); }
const tuple<string> tup4() { return make_tuple("four"); }

int main() {
  // cref(str1()); // BAD, properly rejected
  // cref(str2()); // BAD, properly rejected
  // cref(get<0>(tup3())); // BAD, properly rejected
  cref(get<0>(tup4())); // BAD, but improperly accepted!
}

在这种特殊情况下,cref 删除了 const T&amp;&amp; 的重载,但通过 get 传递它会掩盖元组及其成员是临时的。

【讨论】:

  • 我想知道为什么从std::cref 中删除了这个重载。无论如何,右值都会绑定到const&amp; 版本。那么删除功能提供了什么安全性呢?
  • 因为如果传递给std::cref 的参数是临时的,那么一旦表达式结束,它在内部存储的指针将不再有效。 std::refstd::cref 的一个主要用例是通过引用通常会制作副本的模板函数来传递某些内容,例如std::bindstd::thread
  • 但是不会临时绑定到const&amp; 版本吗?
  • 哦,我明白了。不允许绑定到const&amp;,因为const&amp;&amp; 版本已被删除。就像移动和复制构造函数一样。我说的对吗?
  • 正确。因为存在const T&amp;&amp; 重载,所以选择它作为比const T&amp; 重载更好的匹配。由于也被删除了,所以导致编译失败。
【解决方案2】:

您可以从const&amp;&amp; 中移出可变数据。比较晦涩。

【讨论】:

  • 哦!没有考虑到这一点。但是你不能为普通的const&amp; 这样做吗?
  • @curious 你不知道你是否应该这样做。
  • @curious 对x&amp;&amp; 无能为力,对x&amp; 无能为力,无论是否存在const。右值引用只是说“您有权将其视为临时的,并且可能来自它的蒸汽状态”。使用const&amp;,你不应该窃取可变状态,而const&amp;&amp; 你应该。使用右值引用的方式与使用左值引用的方式不同。
猜你喜欢
  • 1970-01-01
  • 2016-07-19
  • 2020-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
  • 2014-08-31
  • 1970-01-01
相关资源
最近更新 更多