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
_______________________________________________
Boost-users mailing list -- boost-users@lists.boost.org
To unsubscribe send an email to boost-users-le...@lists.boost.org
https://lists.boost.org/mailman3/lists/boost-users.lists.boost.org/
Archived at: https://lists.boost.org/archives/list/boost-users@lists.boost.org/message/P4SXKS5TTEIJMOV4SOBYLALVOU7FSE7F/