
El 06/09/2025 a las 1:50, mail--- via Boost-users escribió:
Consider the following struct:
struct Particle { float scale; float opacity; float rotation; };
I want the following to compile:
static_assert(indexOf<&Particle::scale>() == 0); static_assert(indexOf<&Particle::opacity>() == 1); static_assert(indexOf<&Particle::rotation>() == 2);
I have managed to implement a working version using Boost.PFR:
template <auto PM> consteval int indexOf() { using ClassType = typename PMTraits<decltype(PM)>::ClassType; constexpr ClassType obj{};
std::size_t result = -1;
[&]<auto... Is>(std::index_sequence<Is...>) { (..., ( ( static_cast<const void*>(&(boost::pfr::get<Is>(obj))) == static_cast<const void*>(&(obj.*PM)) ) ? (result = Is) : 0 ) ); }(std::make_index_sequence<boost::pfr::tuple_size_v<ClassType>>{});
return result; }
But I am displeased of the fact that I do need to create an object of type `ClassType` in order to make `obj.*PM` work.
Is there a better way of doing this that (1) does not require the creation of an object at compile-time and/or (2) is more efficient to compile? _______________________________________________
Something like this (fails with Clang and I haven't tried with VS): https://godbolt.org/z/1K36Yfc58 #include <algorithm> #include <array> #include <boost/mp11/algorithm.hpp> #include <boost/pfr/core_name.hpp> #include <boost/type_index/ctti_type_index.hpp> template<auto pm> struct pm_class_impl; template<class C, typename T, T C::*pm> struct pm_class_impl<pm> { using type = C; }; template<auto pm> using pm_class = typename pm_class_impl<pm>::type; template<auto x> struct pm_name_helper{}; template<auto pm> consteval int index_of() { using C = pm_class<pm>; constexpr std::size_t N = boost::pfr::tuple_size_v<C>; std::array<std::string_view, N> names; boost::mp11::mp_for_each<boost::mp11::mp_iota_c<N>>([&](auto I) { names[I] = boost::pfr::get_name<I,C>(); }); std::string_view mangled_pm_name{ boost::typeindex::ctti_type_index::type_id<pm_name_helper<pm>>().raw_name() }; std::string_view pm_name{ mangled_pm_name.begin() + mangled_pm_name.find_last_of(':') + 1, mangled_pm_name.begin() + mangled_pm_name.find_last_of('>') }; return std::find(names.begin(), names.end(), pm_name) - names.begin(); } struct Particle { float scale; float opacity; float rotation; }; int main() { static_assert(index_of<&Particle::scale>() == 0); static_assert(index_of<&Particle::opacity>() == 1); static_assert(index_of<&Particle::rotation>() == 2); } Joaquín M López Muñoz