C++ std::pair分段构造函数中的变量模板问题 //模板构造函数对::对(元组、元组、序列、序列) 样板 模板内联 pair::pair(_Tuple1和_Val1, _图2和图2, 索引_序列, 索引(U序列) :第一个(_stdget(_stdmove(_Val1))…), 第二个(_stdget(_stdmove(_Val2))…) {//从元组对构造 } //模板构造函数对::对(分段构造,元组,元组) 样板 模板内联 pair::pair(分段构造), 元组_Val1, 元组(2) :对(_Val1,_Val2, ()的索引\u序列\u, 索引\u序列\u for()) {//从元组对构造 }

C++ std::pair分段构造函数中的变量模板问题 //模板构造函数对::对(元组、元组、序列、序列) 样板 模板内联 pair::pair(_Tuple1和_Val1, _图2和图2, 索引_序列, 索引(U序列) :第一个(_stdget(_stdmove(_Val1))…), 第二个(_stdget(_stdmove(_Val2))…) {//从元组对构造 } //模板构造函数对::对(分段构造,元组,元组) 样板 模板内联 pair::pair(分段构造), 元组_Val1, 元组(2) :对(_Val1,_Val2, ()的索引\u序列\u, 索引\u序列\u for()) {//从元组对构造 },c++,c++11,visual-c++,C++,C++11,Visual C++,以上是VisualStudio中tuple的源代码。它是std::pair的分段构造函数。第二个构造函数调用第一个构造函数。在第一个构造函数中,第一个和第二个数据成员由 // TEMPLATE CONSTRUCTOR pair::pair(tuple, tuple, sequence, sequence) template<class _Ty1, class _Ty2> template<class _Tuple1, class _Tuple2,

以上是VisualStudio中tuple的源代码。它是std::pair的分段构造函数。第二个构造函数调用第一个构造函数。在第一个构造函数中,第一个和第二个数据成员由

// TEMPLATE CONSTRUCTOR pair::pair(tuple, tuple, sequence, sequence)
template<class _Ty1,
    class _Ty2>
    template<class _Tuple1,
        class _Tuple2,
        size_t... _Indexes1,
        size_t... _Indexes2> inline
        pair<_Ty1, _Ty2>::pair(_Tuple1& _Val1,
            _Tuple2& _Val2,
            index_sequence<_Indexes1...>,
            index_sequence<_Indexes2...>)
        : first(_STD get<_Indexes1>(_STD move(_Val1))...),
            second(_STD get<_Indexes2>(_STD move(_Val2))...)
        {   // construct from pair of tuples
        }

// TEMPLATE CONSTRUCTOR pair::pair(piecewise_construct_t, tuple, tuple)
template<class _Ty1,
    class _Ty2>
    template<class... _Types1,
        class... _Types2> inline
        pair<_Ty1, _Ty2>::pair(piecewise_construct_t,
            tuple<_Types1...> _Val1,
            tuple<_Types2...> _Val2)
        : pair(_Val1, _Val2,
            index_sequence_for<_Types1...>(),
            index_sequence_for<_Types2...>())
        {   // construct from pair of tuples
        }
first(_stdget(_stdmove(_Val1))…),second(_stdget(_stdmove(_Val2))…)

我不明白为什么这里可以使用std::move。如果元组中的某些参数不是右值怎么办?它不会使左值的参数变成右值并调用第一个和第二个的意外构造函数吗?

第一个构造函数不是接口的一部分。它仅由第二个构造函数调用,其中
\u Val1
\u Val2
按值传递,因此第一个构造函数可以移动它们

由于调用了
std::move
,因此可以在此处调用的
std::get
的重载有:

first(_STD get<_Indexes1>(_STD move(_Val1))...), second(_STD get<_Indexes2>(_STD move(_Val2))...)
template
typename std::元组元素::类型&&
get(tuple&&t)noexcept;
模板
typename std::tuple_元素::type const&&
get(const tuple&&t)noexcept;

在这两种情况下,如果
typename std::tuple\u element::type
是左值引用,则返回类型将保持左值引用,因为
T&&
只是
T&
。因此,元组的左值引用元素上不能发生移动。

如果可变参数中的一个参数是引用类型,则即使元组按值传递,它仍将是引用相同引用的引用类型。我说得对吗?是的,你说得对。虽然我看不出这有什么问题。如果可变参数的参数arg0是引用类型,调用传递值元组上的move()是否会使arg0成为右值,并在调用第一个构造函数后使其处于无效状态?
std::move(t)
不会返回
t&
,而是返回
t&
。在这之后,
U&
会发生什么取决于
std::get
在本例中的作用,我已经澄清了这一点。
template< std::size_t I, class... Types >
typename std::tuple_element<I, tuple<Types...> >::type&&
get( tuple<Types...>&& t ) noexcept;

template< std::size_t I, class... Types >
typename std::tuple_element<I, tuple<Types...> >::type const&&
get( const tuple<Types...>&& t ) noexcept;