#include <iostream>
#include <tuple>
#include <type_traits>
using namespace std;
template<typename T>
struct Public : public T
{
using unspecied_type = T;
};
template<typename T>
struct Private : protected T
{
using unspecied_type = T;
};
template<typename T>
struct InheritanceSpecifierAdder
{
using specified_type = Public<T>;
};
template<typename T>
struct InheritanceSpecifierAdder<Private<T>>
{
using specified_type = Private<T>;
};
template<typename T>
using AddAccessSpecifier = typename InheritanceSpecifierAdder<T>::specified_type;
template<typename... Ts>
class inheriter : public AddAccessSpecifier<Ts>...
{
public:
using ThisInheriter = inheriter<Ts...>;
};
namespace impl
{
template<size_t, typename>
struct inherited_helper;
template<size_t Index, typename... Ts>
struct inherited_helper<Index, inheriter<Ts...>>
{
using type = typename std::tuple_element<Index, std::tuple<Ts...>>::type;
};
} // namespace impl
template<size_t Index, typename T>
using inherited = typename impl::inherited_helper<Index, typename T::ThisInheriter>::type;
#define KMU_BASE(type) \
using ThisInheriter = type;
#define THIS_TYPE \
typename std::remove_reference<typename std::remove_const<decltype(*this)>::type>::type
#define INHERITED(Index) inherited<(Index), THIS_TYPE>
#define SUPER INHERITED(0)
//-----------------------------------------------------------------------------
struct A
{
KMU_BASE(A);
};
struct B : public inheriter<A>
{};
struct C : public inheriter<A>
{};
struct D : public inheriter<Public<B>, Public<C>>
{};
struct E : public inheriter<Public<B>, Private<C>>
{};
struct F;
#define DBG(X) void f(const X&) { std::cout << #X << "\n"; }
DBG(A);
DBG(B);
DBG(C);
DBG(D);
DBG(E);
DBG(F);
struct F : public inheriter<Private<E>>
{
F()
{
f(SUPER{});
}
};
//--------------------------------------------------------
int main()
{
f(inherited<0, D>{});
f(inherited<1, D>{});
F fff;
//f(inherited<0, F>{}); // error --> E private
std::cout << "\n" << sizeof(F) << "\n";
return 0;
}