Различное поведение при попытке заменить две переменные с помощью {} и std:: make_pair()

Я пытался обменять две переменные с помощью std::tie() в соответствии с следующим кодом (я знаю std::swap, я просто пытался это из любопытства):

#include <iostream>
#include <tuple>

using std::cin; using std::tie; 
using std::cout; using std::endl;
using std::make_pair;

int main() {
    int a = 2, b = 10;
    cout << "Before Swapping using {}" << endl;
    cout << "a: " << a << " b: " << b < <endl;
    tie(a, b) = {b, a};
    cout << "After Swapping using {}" << endl;
    cout << "a: " << a << " b: " << b << endl;

    a = 2, b = 10;
    cout << "Before Swapping using make_pair()" << endl;
    cout << "a: " << a << " b: " << b << endl;
    tie(a, b) = make_pair(b, a);
    cout << "After Swapping using make_pair()" << endl;
    cout << "a: " << a << " b: " << b << endl;    

    return 0;
}

Я скомпилировал его с помощью g++ test.cpp -std=c++11 -o test.

Но результат был следующим:

Before Swapping using {}
a: 2 b: 10
After Swapping using {}
a: 10 b: 10
Before Swapping using make_pair()
a: 2 b: 10
After Swapping using make_pair()
a: 10 b: 2

Итак, мой вопрос заключается в том, что мы можем писать {a, b} вместо того, чтобы писать std::make_pair(a, b) каждый раз (С++ 11), почему эти две версии дают разные результаты?

Я предполагал, что следующая строка

std::tie(a, b) = {b, a};

не создает пару и по какой-то причине только мутирует значение a. Но я не уверен.

Ответ 1

tie(a, b) = {b, a};

будет использовать std::tuple<int&, int&> operator = (std::tuple<int&, int&>&&). и не std::tuple<int&, int&> operator = (std::tuple<int, int>&&), как вы ожидаете.

std::tie(a, b) - это std::tuple<int&, int&>.
std::tuple имеет несколько operator =, но единственной жизнеспособной с (не типизированной) {a, b} является назначение копирования/перемещения.

Ответ 2

{b, a} делает std::tuple<int&, int&>, а std::make_pair делает std::pair<int, int>.

Рассмотрим, что происходит с std::pair<int&, int&>. Он по существу назначает одну из переменных другой, а затем пытается назначить другую первой. Это эквивалентно выполнению a = b; b = a; или b = a; a = b;.

Ответ 3

просто используйте make_tuple

std::tie(a, b) = std::make_tuple(b, a);

это то же самое a = b или b = a;