Home > database >  C concept to check for derived from template specialization
C concept to check for derived from template specialization

Time:11-27

In this SO answer and this proposal we can see an implementation (included below for convenience) for std::is_specialization_of, which can detect if a type is a specialization of a given template.

template< class T, template<class...> class Primary >
struct is_specialization_of : false_type;

template< template<class...> class Primary, class... Args >
struct is_specialization_of< Primary<Args...>, Primary> : true_type;

The proposal explicitly says that this type trait is not affected by inheritance:

The proposed trait considers only specialization. Since specialization is unrelated to inheritance, the trait’s result is unaffected when any template argument happens to be defined via inheritance.

template< class > struct B { };
template< class T > struct D : B<T> { };

static_assert(     is_specialization_of_v< B<int>, B> );
static_assert(     is_specialization_of_v< D<int>, D> );

static_assert( not is_specialization_of_v< B<int>, D> );
static_assert( not is_specialization_of_v< D<int>, B> );

Is there a way to implement something that does take inheritance into consideration, behaving like std::derived_from but where the Base could be any specialization of a given template? Something like, say std::derived_from_specialization_of:

template<class>   struct A {};
template<class T> struct B : A<T> {};
template<class T> struct C : B<T> {};

static_assert(derived_from_specialization_of< A<int>, A>);
static_assert(derived_from_specialization_of< B<int>, B>);
static_assert(derived_from_specialization_of< C<int>, C>);

static_assert(derived_from_specialization_of< B<int>, A>);
static_assert(derived_from_specialization_of< C<int>, B>);
static_assert(derived_from_specialization_of< C<int>, A>);

It should also support templates with multiple parameters, and/or parameter packs:

template<class, class> struct A{};
template<typename...>  struct B{};

CodePudding user response:

De-_Ugly-fied rom MSVCSTL:

template <template <class...> class Template, class... Args>
void derived_from_specialization_impl(const Template<Args...>&);

template <class T, template <class...> class Template>
concept derived_from_specialization_of = requires(const T& t) {
    derived_from_specialization_impl<Template>(t);
};

which we use to implement the exposition-only type trait is-derived-from-view-interface from [range.view]/6.

Note that this has the same limitation as the is_specialization_of trait cited in the OP: it works only with templates that have all type parameters.

[DEMO]

  • Related