Я изучаю объявления структурированной привязки. Насколько я понял, в auto& [x, y] = expr;
введены переменные x
и y
типа "ссылка на std::tuple_element<i, E>::type
" (ибо i=0, 1
и E
это тип невидимой переменной e
). Более того, эти переменные инициализируются с помощью get<i>(e)
.
Итак, если я использую auto&
, а get<>
возвращает значение (не ссылку), оно не должно компилироваться, так как вы не можете привязать lvalue к временному. Однако следующий пример создается для меня в некоторых версиях GCC, Clang и Visual Studio:
#include <cstddef>
#include <tuple>
#include <type_traits>
struct Foo {
template<std::size_t i>
int get() { return 123; }
};
namespace std {
template<> struct tuple_size<Foo> : integral_constant<size_t, 1> {};
template<std::size_t i> struct tuple_element<i, Foo> { using type = int; };
}
int main() {
Foo f;
auto& [x] = f;
x++;
}
Более того, C++ Insights ясно показывает, что clang расширяет структурированную привязку до:
Foo f = Foo();
Foo & __f17 = f;
std::tuple_element<0, Foo>::type x = __f17.get<0>();
x++;
Здесь он объявляет x
не как ссылку, а как значение. Почему это?
Я ожидал ссылки на lvalue и ошибку компиляции: e
(__f17
в приведенном выше примере) — это ссылка на lvalue.