c ++ 11 — c ++ рекурсивно вложенные типы и внедрение имен

Я попытался найти это без удачи, поэтому я пытаюсь здесь.

У меня есть пара классов, каждый из которых определяет член struct foo, Этот тип участника foo может сам наследовать от одного из прежних классов, следовательно, получая тип члена foo сам.

Я хочу получить доступ к вложенным foo типы, использующие шаблонное метапрограммирование (см. ниже), но внедрение имени в c ++ создает проблемы, так как верхний foo имя типа вводится в нижний foo типа, и верхний разрешается, когда я хочу получить доступ к нижнему, скажем, с помощью A::foo::foo,

Вот пример:

#include <type_traits>

struct A;
struct B;

struct A {
struct foo;
};

struct B {
struct foo;
};

struct A::foo : B { };
struct B::foo : A { };

// handy c++11 shorthand
template<class T>
using foo = typename T::foo;

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)" );

К вашему сведению, я реализую производные функции, foo является производным типом. Вышеуказанная ситуация происходит, например, с грехом / cos.

TLDR: как я могу получить foo<foo<A>> быть foo<B>не foo<A> ?

Спасибо !

11

Решение

Это на самом деле не автоматическое решение, но решает проблему. Ваш
Типы предоставляют 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;
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]