Search code examples
c++templatesc++20template-meta-programming

Obtaining a type from a base class


Suppose we have

class Derived : public Base1, public Base2, ..., public Base<Ts...>> {};

How to write a class that obtains the type std::tuple<Ts...> from Derived? Perhaps Base needs to be passed as a template argument too, to specify which base class to search for.

Providing my concrete example here will be overwhelming to read. Let's just say I need the Ts... in order to count how many of them satisfy a certain predicate. This number is the constexpr int I need for each derived class, but I need to obtain the Ts... first.


Solution

  • Since you publically and unambiguously inherit from a Base<Ts...>, you can use template argument deduction to get the Ts...: https://godbolt.org/z/oWfe3z16j

    #include <type_traits>
    #include <tuple>
    
    namespace detail {
    template<template<typename...> class Base, typename... Args> std::type_identity<std::tuple<Args...>> extract_base_args_impl(Base<Args...>*);
    }
    
    template<template<typename...> class Base, class Derived>
    using extract_base_args_t = decltype(detail::extract_base_args_impl<Base>(static_cast<std::remove_cv_t<Derived>*>(nullptr)))::type;
    
    template<template<typename...> class Base, class Derived>
    struct extract_base_args {};
    
    template<template<typename...> class Base, class Derived>
    requires(requires { typename extract_base_args_t<Base, Derived>; })
    struct extract_base_args<Base, Derived> {
        using type = extract_base_args_t<Base, Derived>;
    };
    

    Where you can make Base whatever template class you like.