Ответ 1
Это не автоматическое решение, но решает проблему. Ваш типы предоставляют typedef базовому классу, отсутствие/наличие этого typedef обнаруживается через SFINAE, и вложенный foo находится либо через базу или через обычный поиск.
Возможно, вы можете автоматизировать has_base
, чтобы проверить список известных
базы с is_base_of
, если вам нужна дополнительная автоматизация.
#include <type_traits>
template <typename T>
struct has_base
{
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::base*);
template <typename>
static no& test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
struct A {
struct foo;
};
struct B {
struct foo;
};
struct A::foo : B { typedef B base; };
struct B::foo : A { typedef A base; };
template<typename T, bool from_base = has_base<T>::value >
struct foo_impl {
typedef typename T::base::foo type;
};
template<typename T>
struct foo_impl<T, false> {
typedef typename T::foo type;
};
template<typename T>
using foo = typename foo_impl<T>::type;
static_assert( std::is_same< foo< foo<A> >::, foo< B > >::value,
"this should not fail (but it does)" );
static_assert( std::is_same< foo< foo< A > >, foo< A > >::value,
"this should fail (but it does not)" );
int main()
{
return 0;
}