sintaxis - c++ tipos anidados recursivamente e inyección de nombre
sintaxis de recursividad (1)
Esto no es realmente una solución automática, pero resuelve el problema. Sus tipos proporcionan un typedef a la clase base, la ausencia / presencia de este tipodef se detecta a través de SFINAE y el foo anidado se encuentra a través de la base o mediante la búsqueda normal.
Probablemente puedas automatizar has_base
para verificar una lista de bases conocidas con is_base_of
si necesitas más automatización.
#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;
}
Intenté buscar en Google esto sin suerte, así que lo estoy intentando aquí.
Tengo un par de clases, cada una de las cuales define un miembro struct foo
. Este tipo de miembro foo
puede heredarse de una de las clases anteriores, obteniendo de este modo un tipo de miembro foo
.
Quiero acceder a los tipos de foo
anidados utilizando la metaprogramación de plantillas (ver a continuación), pero la inyección de nombres de c ++ presenta problemas, ya que el nombre del tipo de foo
superior se inyecta en el tipo de foo
inferior, y el superior se resuelve cuando quiero acceder al inferior , digamos usando A::foo::foo
.
Aquí hay un ejemplo:
#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)" );
Para su información, estoy implementando derivados de función, foo
es el tipo derivado. La situación anterior ocurre, por ejemplo, con sin / cos.
TLDR: ¿cómo hago que foo<foo<A>>
sea foo<B>
, no foo<A>
?
Gracias !