posting my comments on twitter here
obviouslyObviously you should use reflection instead but this is the idea
https://godbolt.org/z/8Mzjx8K5Y
#include <tuple>
#include <type_traits>
template <std::size_t N, auto ptr, class T>
constexpr bool isCorrect(const T& t) {
auto&&[... ref] = t;
auto tuple = std::tie(ref...);
auto* actual = std::addressof(t.*ptr);
auto* expected = std::addressof(std::get<N>(tuple));
if constexpr (std::is_same_v<decltype(actual), decltype(expected)>) {
return actual == expected;
} else {
return false;
}
}
template <std::size_t N, auto ptr, class T>
constexpr auto find_impl(const T& t) {
if constexpr(isCorrect<N, ptr>(t)) {
return std::cw<N>;
} else {
return find_impl<N+1, ptr>(t);
}
}
template <auto Ptr> struct member_class;
template <class C, class M, M C::* Ptr>
struct member_class<Ptr> {
using type = C;
};
template <auto ptr>
inline constexpr auto index_of = decltype(find_impl<0, ptr>(std::declval<typename member_class<ptr>::type>()))::value;
struct X {
int a;
double b;
int c;
};
static_assert(index_of<&X::a> == 0);
static_assert(index_of<&X::b> == 1);
static_assert(index_of<&X::c> == 2);
How are you able to pass a runtime parameter in if constexpr
That is what P2280 about. We don’t care about the identity of the parameter, all objects of the type will produce the same results. This is DRed to all versions
what's
std::cw
Just a short hand creating a wrapper into a type from a value. If you don’t have 26, replace it with integral_constant<size_t, N>{}
Is it all 26
The only thing that you can’t really do without 26 is the structured binding introducing a pack. But you can replace it with boost.pfr ( I did not check its implementation, but I guess it just try using structure bindings for N members and select one that succeed