C++ std::tuple::get返回的常量类型&&;

C++ std::tuple::get返回的常量类型&&;,c++,tuples,c++14,rvalue-reference,c++17,C++,Tuples,C++14,Rvalue Reference,C++17,我刚刚在cppreference上阅读了C++17的更新接口,用于std::tuple::get,新的重载从get()函数返回const Type&&。为什么只在常规的常量类型上返回常量类型&&?无法从这两种类型的实例中移动 这些是我所指的函数声明,仅供参考 template< class T, class... Types > constexpr const T&& get(const tuple<Types...>&& t); 模板

我刚刚在cppreference上阅读了C++17的更新接口,用于
std::tuple::get
,新的重载从
get()
函数返回
const Type&&
。为什么只在常规的
常量类型上返回
常量类型&&
?无法从这两种类型的实例中移动

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

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

template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >const&&
get( const tuple<Types...>&& t );
template
constexpr std::元组元素&&
get(常量元组和&t);

您可以从
常量和&
移动可变数据。它相对来说比较模糊。

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

#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!
}
#包括
#包括
#包括
使用名称空间std;
字符串str1(){返回“一”;}
常量字符串str2(){return“two”;}
tuple tup3(){返回make_tuple(“三”);}
const tuple tup4(){return make_tuple(“four”);}
int main(){
//cref(str1());//错误,正确拒绝
//cref(str2());//错误,正确拒绝
//cref(get(tup3());//错误,正确拒绝
cref(get(tup4());//错误,但被不正确地接受!
}

在这种特殊情况下,
cref
常量T&
有一个已删除的重载,但是通过
get
传递它会掩盖元组及其成员是临时的。

通过这种方式,您可以完美地转发文本抛出整个调用
double d=std::get(std::make_tuple(1,“Foo”,3.14))@HenriMenke我想他们问的是返回,不是转发。哦!我没想过。但是对于一个常规的
常量&
你不能这样做吗?@好奇的是,你不知道你是否应该这样做。@好奇的是,你对
x&&
无能为力,无论是否有
常量&
,你都不能对
x&
这样做。一个右值引用只是说“您有权将其视为临时状态,可能是来自它的蒸汽状态”。使用
const&
时,您不应该窃取可变状态,而不是
const&
您应该这样做。您应该如何使用右值引用与您应该如何使用左值引用不同。我想知道为什么会从
std::cref
中删除该重载。。R值无论如何都会绑定到
常量&
版本。那么,删除的函数提供了什么安全性呢?因为如果传递给
std::cref
的参数是临时的,那么它内部存储的指针在表达式结束时就不再有效。
std::ref
std::cref
的一个主要用例是通过引用将某些内容传递给通常会制作副本的模板函数,例如
std::bind
std::thread
但是临时绑定到
const&
版本不会吗?哦,我理解。由于删除了
const&
版本,因此不允许绑定到
const&
。就像移动和复制构造函数一样。。我说的对吗?对。由于存在
const T&
重载,因此选择它比
const T&
重载更匹配。由于它也被删除,因此会导致编译失败。