Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Concept that ensures a type is defined for all indexes in a sequence

I have an indexable type trait, that can be specialized:

// Traits
template <size_t Idx, typename T>
struct nth_type;

template <size_t Idx, typename T>
using nth_type_t = typename nth_type<Idx, T>::type;

template <typename T>
struct num_types;

template <typename T>
inline constexpr size_t num_types_v = num_types<T>::value;

// Specialization
template <typename... Ts>
struct type_sequence {};

template <size_t Idx, typename... Ts>
struct nth_type<Idx, type_sequence<Ts...>>
  : std::type_identity<std::tuple_element_t<Idx, std::tuple<Ts...>>
{};

template <typename... Ts>
struct num_types<type_sequence<Ts...>>
{
    static constexpr size_t value = sizeof...(Ts);
};

How can I write a concept that requires that typename nth_type<Idx, T> is valid and names a type for every value in [0, num_types_v<T>)

i.e.:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

template<typename T>
concept has_types = requires {
  typename nth_type<0, T>;
  typename nth_type<1, T>;
  // ...
  typename nth_type<num_types<T> - 1, T>;
};

>Solution :

It always helps to break the problem down into pieces.

First, write the concept for whether the Ith type is defined:

template <size_t I, typename T>
concept has_nth_type = requires {
  typename nth_type<I, T>;
};

Next, we can write a helper function to explode an index. That is, indices<4>(f) calls f(0, 1, 2, 3) except instead of 0 it’s integral_constant<size_t, 0>{}, which preserves the constant-ness of the value better. This is just a generally-useful utility:

template <size_t N, class F>
constexpr auto indices(F&& f) -> decltype(auto) {
    return [&]<size_t... Is>(std::index_sequence<Is...>) -> decltype(auto) {
        return f(std::integral_constant<size_t, Is>{}...);
    }(std::make_index_sequence<N>{});
}

Lastly, we combine those two together:

template<typename T>
concept has_types =
    indices<num_types_v<T>>([](auto... Is){
        return (has_nth_type<Is, T> and ...);
    });
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading