#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;
}