Поддерживать тип ссылки на элемент пары - PullRequest
0 голосов
/ 08 мая 2019

Есть ли способ переслать элемент пары (или кортежа) при сохранении его ссылочного типа (например, продолжать быть значением)?

В приведенном ниже примере демонстрируется то, что я пробовал: пересылка и перемещение элементов пары (первой и второй), перемещение пары и использование ее элементов, а также перемещение как пары, так и элементов. Я ожидал бы, что все будут работать, но никто из них не делает.

template<class T, class U>
auto pair_forward(std::pair<T, U>&& p)
{
    return std::make_pair(std::forward<T>(p.first), std::forward<U>(p.second));
}

template<class T, class U>
auto pair_move_elem(std::pair<T, U>&& p)
{
    return std::make_pair(std::move(p.first), std::move(p.second));
}

template<class T, class U>
auto move_pair(std::pair<T, U>&& p)
{
    return std::make_pair(std::move(p).first, std::move(p).second);
}

int main()
{
    int x;
    std::pair<int, int&&> p(x, std::move(x));
    static_assert(std::is_rvalue_reference<decltype(p.second)>::value); // works

    auto t1 = pair_forward(std::move(p));
    static_assert(std::is_rvalue_reference<decltype(t1.second)>::value); // fails

    auto t2 = pair_move_elem(std::move(p));
    static_assert(std::is_rvalue_reference<decltype(t2.second)>::value); // fails

    auto t3 = move_pair(std::move(p));
    static_assert(std::is_rvalue_reference<decltype(t3.second)>::value); // fails
}

1 Ответ

0 голосов
/ 08 мая 2019

Правила дедукции для make_pair меня сбивают с толку, поэтому я предлагаю просто вызвать конструктор напрямую с нужными вам типами.

#include <utility>

template<class T, class U>
auto pair_forward(std::pair<T, U>&& p)
{
    return std::pair<T, U>(std::forward<T>(p.first), std::forward<U>(p.second));
}

template<class T, class U>
auto pair_move_elem(std::pair<T, U>&& p)
{
    return std::pair<T&&, U&&>(std::move(p.first), std::move(p.second));
}

template<class T, class U>
auto move_pair(std::pair<T, U>&& p)
{
    return std::pair<T, U>(std::move(p));
    // or just: return std::pair(std::move(p));
}

int main()
{
    int x;
    std::pair<int, int&&> p(x, std::move(x));
    static_assert(std::is_rvalue_reference<decltype(p.second)>::value); // works

    auto t1 = pair_forward(std::move(p));
    static_assert(std::is_rvalue_reference<decltype(t1.second)>::value); // works

    auto t2 = pair_move_elem(std::move(p));
    static_assert(std::is_rvalue_reference<decltype(t2.second)>::value); // works

    auto t3 = move_pair(std::move(p));
    static_assert(std::is_rvalue_reference<decltype(t3.second)>::value); // works
}

в прямом эфире: https://godbolt.org/z/EfGe_x

...