Decltype of struct data members, using structured binding

I think you can do something like this:

#include <type_traits>

template <typename T, typename U>
struct Identity {
  using type_first = T;
  using type_second = U;
};

template <typename T>
constexpr auto GetTypes(const T& obj) noexcept {
  const auto& [x, y] = obj;
  return Identity<std::remove_cv_t<decltype(x)>, 
                  std::remove_cv_t<decltype(y)>>{};
}

template <typename T>
void foo(T obj) {
  // T is structurally-bindable with two fields
  constexpr auto Types = GetTypes(obj);
  using t1 = typename decltype(Types)::type_first;
  using t2 = typename decltype(Types)::type_second;

  // t1 is the first type
  // t2 is the second type
}

Complete Example Here

Note that with constexpr there is no overhead, even without enabling optimizations.


Probably you can add one extra structured binding before last_from declaration and take from type from it. I.e.

const auto& [first_from, first_to] = *range_of_tuple_or_struct_or_pair.begin();
last_from = std::numeric_limits<std::decay_t<decltype(first_from)>>::max();

Not quite cool, but maybe will work