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/

Reply via email to