rbtrht
rbtrht

Reputation: 219

Structural binding and type of variables

I would like to ask a question about structural binding and how the variables get their types. Here is the code I compile.

struct T {
  explicit T(int a = 1) {
    a_ = a;
    std::cout << "Default" << std::endl;
  }
  T(const T& t) {
    a_ = t.a_;
    std::cout << "Copy" << std::endl;
  }
  int a_;
};

int main() {

  std::tuple<bool, T> bi{true, T(1)};
  std::cout << "START" << std::endl;
  auto& [b, i] = bi;
  static_assert(std::is_same<decltype(i), T>::value);
  std::cout << i.a_ << std::endl;
  i.a_++;
  std::cout << i.a_ << std::endl;
  std::cout << (&i == &get<1>(bi)) << std::endl;


  return 0;
}

The code compiles and the result is:

Default
Copy
START
1
2
1

As you can see the variable i actually refers to get<1>(bi). However, the type of the variable i is T since std::is_same<decltype(i), T>::value. Could you please explain why structural binding works this way? I have read about it in the book "C++ Templates: The Complete Guide" and the authors state that the variable i must have type std::tuple_element<1, std::tuple<bool, T> >::type&&. I don't understand why decltype(i) is just T.

Upvotes: 1

Views: 318

Answers (1)

decltype is funny that way. Its specification contains a special clause for structured bindings

4 For an expression e, the type denoted by decltype(e) is defined as follows:

  • if e is an unparenthesized id-expression naming a structured binding ([dcl.struct.bind]), decltype(e) is the referenced type as given in the specification of the structured binding declaration;

  • ...

So while each structured binding is indeed a reference into the tuple, decltype reports the type of the referent. Likely since structured bindings are meant to feel like regular named variables.

Upvotes: 3

Related Questions