Вопрос шаблона Variadic в кусочном конструкторе std :: pair - PullRequest
0 голосов
/ 04 января 2019
// 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
        }

Выше приведен исходный код кортежа в VisualStudio.Это кусочный конструктор std :: pair.Второй конструктор вызывает первый.В первом конструкторе, элемент данных first и second инициализируются как

first(_STD get<_Indexes1>(_STD move(_Val1))...), second(_STD get<_Indexes2>(_STD move(_Val2))...)

. Я не понимаю, почему здесь можно использовать std :: move.Что если некоторые аргументы в кортеже не являются значением?Разве это не приводит аргументы, которые являются lvalues, чтобы стать rvalues ​​и вызывать непреднамеренный конструктор первого и второго?

1 Ответ

0 голосов
/ 04 января 2019

Первый конструктор не является частью интерфейса.Он вызывается для делегирования только вторым, где _Val1 и _Val2 передаются по значению, поэтому первый конструктор может их перемещать.

Из-за вызова std::move перегрузки 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;

В обоих случаях, если typename std::tuple_element<I, tuple<Types...> >::type является ссылкой lvalue, возвращаемый тип остается ссылкой lvalue, потому что T& && - это просто T&.Таким образом, в lvalue ссылочных элементах кортежа не может быть никакого перемещения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...