Skip to main content
Removed irrelevant text
Source Link
Gert Arnold
  • 110.1k
  • 36
  • 219
  • 319

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

posting my comments on twitter here

obviously 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

Obviously 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

Source Link
Hui
  • 591
  • 1
  • 3
  • 10

posting my comments on twitter here

obviously 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