c++11templatesinheritancestaticpolicy-based-design

Accessing static data through inheritance of a template template parameter?


template
<
    template <typename, typename>
        class storage_t,
    typename T,
    typename is_allocated
>
class Buffer : public storage_t<T, is_allocated> { ... };

template
<
    template <typename, typename>
        class storage_t,
    typename T = storage::UnknownType,
    typename is_allocated = std::false_type
>
class Example_Buffer
: public Buffer<storage_t, T, is_allocated> {
    constexpr Example_Buffer(
        typename storage_t<T, is_allocated>::iterator it) {}
};

Example_Buffer<...> inherits from Buffer<...>. Buffer<storage_t, T, is_allocated> inherits from storage_t<T, is_allocated>. storage_t<...> includes typedefs and static constexpr data. Is there a way to access these typedefs and static constexpr data in the constructor of Example_Buffer through inheritance? (through inheritance, that is, not using storage_t<T, is_allocated>? It feels slightly odd to use this syntax twice within the same class.

Feel free to ask if I need to elaborate.


Solution

  • The members are inherited and accessible as long as they are public in storage_t. You can use the injected class name and/or the injected base class name to access these dependent members,

    Here are a few options..

    #include <iostream>
    #include <type_traits>
    #include <typeinfo>
    
    using namespace std;
    
    template <typename A,typename B>
    struct basic_storage
    {
        using a_type = A;
        using b_type = B;
        static constexpr bool value = b_type::value;
    };
    
    
    template
    <
        template <typename, typename>
            class storage_t,
        typename T,
        typename is_allocated
    >
    class Buffer : public storage_t<T, is_allocated> {
    
        public:
        using storage_type = storage_t<T, is_allocated>;
    };
    
    template
    <
        template <typename, typename>
            class storage_t,
        typename T /*= storage::UnknownType*/,
        typename is_allocated = std::false_type
    >
    class Example_Buffer
    : public Buffer<storage_t, T, is_allocated> {
        public:
        constexpr Example_Buffer(
            /*typename storage_t<T, is_allocated>::iterator it*/) {
    
                //using the members with the injected class name..
                using b_type = typename Example_Buffer::b_type;
    
                // or directly using injected class name..
                std::cout << typeid(typename Example_Buffer::a_type).name() << std::endl;
                std::cout << Example_Buffer::value << std::endl;
    
                // using storage_type defined in Buffer<...>
                using storage_type = typename Example_Buffer::storage_type;
    
                std::cout << typeid(typename storage_type::a_type).name() << std::endl;
                std::cout << storage_type::b_type::value << std::endl;
                std::cout << storage_type::value << std::endl;
    
            }
    };
    
    
    int main() {
        Example_Buffer<basic_storage,int,std::true_type>{};
        return 0;
    }
    

    Demo

    If your wondering why you cant just access then in the derived class without prefixing them with Example_Buffer:: base class name, as this post explains it is because they are dependent names.