Take a look at this innocent piece of code:
vector<vector<int>> arr{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
};
int n = arr.size();
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n/2; j++) {
tie(arr[i][j], arr[j][n-i-1], arr[n-i-1][n-j-1], arr[n-j-1][i]) =
{arr[j][n-i-1], arr[n-i-1][n-j-1], arr[n-j-1][i], arr[i][j]};
//tie(arr[i][j], arr[j][n-i-1], arr[n-i-1][n-j-1], arr[n-j-1][i]) =
// tuple{arr[j][n-i-1], arr[n-i-1][n-j-1], arr[n-j-1][i], arr[i][j]};
}
}
for (auto& i : arr) {
for (int j : i)
cout << j << ' ';
cout << '\n';
}
Outputs (with optimizations disabled):
4 8 12 16
3 7 11 15
8 7 10 14
4 3 9 13
which is totally gibberish.
Using tuple{}
instead of initializer list ({}
) for tie()
gives the correct answer. This behavior is observed both on GCC and clang.
In fact, this is present with code as simple as this:
int a = 1, b = 2;
tie(a, b) = {b, a};
This once again shows one of the dark sides of C++. Hope no one spends 30 mins searching for such bug after this blog :):