Downcasting dinâmico C ++ para modelo de classe com parâmetro de modelo de modelo sendo um modelo de classe ou um modelo de alias

Espero que o título faça sentido. Provavelmente sinto falta do vocabulário para expressá-lo corretamente.

Bem, um exemplo provavelmente será mais claro.

O problema para mim é: o downcast dinâmico retorna 0 no tempo de execução em alguns dos seguintes casos (escritos em comentários). Gostaria de saber se é um comportamento correto (usando C ++ 11), também o porquê e o que posso fazer para fazê-lo funcionar. Aparentemente, Templated e A :: A_templated são tratados como classes diferentes, apesar de serem definidos como idênticos usando o alias "using". O problema não aparece para um alias simples de typedef.

template <class T>
class Templated {};

class A {
    public :
    typedef int A_Type;
    template <class T>
    using A_Templated = Templated<T>;
};

class Test_base {
    public :
    Test_base() {}
    virtual void foo()=0;
};

template <class T>
class Test_Type : public Test_base {
    public :
    Test_Type() {}
    void foo() {}
};

template < template <class T> class TT >
class Test_Templated : public Test_base {
    public :
    Test_Templated() {}
    void foo() {}
};

int main() {
    Test_base* test;

    test = new Test_Type<int>;
    std::cout << dynamic_cast< Test_Type<int>* >(test) << std::endl;//-->ok
    std::cout << dynamic_cast< Test_Type<A::A_Type>* >(test) << std::endl;//-->ok

    test = new Test_Templated<Templated>;
    std::cout << dynamic_cast< Test_Templated<Templated>* >(test) << std::endl;//-->ok
    std::cout << dynamic_cast< Test_Templated<A::A_Templated>* >(test) << std::endl;//--> returns 0 !

    test = new Test_Templated<A::A_Templated>;
    std::cout << dynamic_cast< Test_Templated<A::A_Templated>* >(test) << std::endl;//-->ok
    std::cout << dynamic_cast< Test_Templated<Templated>* >(test) << std::endl;//--> returns 0 !


}

Proponho outra maneira de ver o problema, isso provavelmente é mais claro. Estou enfrentando isso depois de tentar evitar o exemplo acima. O exemplo a seguir diz basicamente o que Bogdan apontou. Acho muito frustrante o fato de o compilador não conseguir resolver o Templated com Templated_alias. Gostaria de saber se existe uma opção de compilação, que pode classificar o tipo de força que resolve através de aliases de modelo.

template <class T>
class Templated {};

template <class T>
using Templated_alias = Templated<T>;

template < template <class T> class TT >
class B;

template <>
class B<Templated> {
    public :
    void foo(Templated<int> _arg) {}
};

int main() {
    B<Templated> b1;
    b1.foo(Templated<int>());
    b1.foo(Templated_alias<int>());//compiles => Templated_alias<int> is equivalent to Templated<int>
    B<Templated_alias> b2;//Compilation error: Implicit instantiation of undefined template B<Templated_alias>
    //which means: Templated_alias is not equivalent to Templated
}

Graças ao truque de Bogdan, e depois de um pequeno sangramento no nariz, consegui encontrar algum tipo de solução. A idéia é criar uma classe encarregada de 'filtrar' aliases potenciais de classes de modelo. Ele precisa de uma especificação por classe de modelo necessária para ser 'filtrada'. A principal desvantagem do método é que a filtragem precisa, portanto, ser usada em todos os lugares onde as classes de modelo são usadas como parâmetros do modelo para ser consistente.

//Classes to be dealt with

template <class T>
class Templated {};

template <class T>
class Templated2 {};

template <class T>
using Templated_alias = Templated<T>;

class A_base {
    virtual void foo()=0;
};

template <template <class T> class TT>
class A : public A_base {
    void foo() {}
};

//Here starts the trick definition

template<template<class> class TT1, template<class> class TT2>
using is_same_template_t = typename std::is_same<TT1<int>, TT2<int> >::type;

//Template Template aliasing
template < template <class T> class TT >
class TT_aliasing {
    public :
    template <class T>
    using Class_T = TT<T>;
};

//Template Template Alias Filtering
template < template <class T> class TT, class = std::true_type>
class TT_AF {
    public :
    template <class T>
    using Class_T = TT<T>;
};

template < template <class T> class TT >
class TT_AF<TT, is_same_template_t<TT, Templated> > : public TT_aliasing<Templated> {};

int main() {

    A_base* a;
    a = new A< TT_AF<Templated>::Class_T >();
    std::cout << dynamic_cast< A< TT_AF<Templated>::Class_T >* >(a) << std::endl;
    std::cout << dynamic_cast< A< TT_AF<Templated_alias>::Class_T >* >(a) << std::endl;
    std::cout << dynamic_cast< A< TT_AF<Templated2>::Class_T >* >(a) << std::endl;

    std::cout << "---------------" << std::endl;

    a = new A< TT_AF<Templated_alias>::Class_T >();
    std::cout << dynamic_cast< A< TT_AF<Templated>::Class_T >* >(a) << std::endl;
    std::cout << dynamic_cast< A< TT_AF<Templated_alias>::Class_T >* >(a) << std::endl;
    std::cout << dynamic_cast< A< TT_AF<Templated2>::Class_T >* >(a) << std::endl;

    std::cout << "---------------" << std::endl;

    a = new A< TT_AF<Templated2>::Class_T >();
    std::cout << dynamic_cast< A< TT_AF<Templated>::Class_T >* >(a) << std::endl;
    std::cout << dynamic_cast< A< TT_AF<Templated_alias>::Class_T >* >(a) << std::endl;
    std::cout << dynamic_cast< A< TT_AF<Templated2>::Class_T >* >(a) << std::endl;

    A< TT_AF<Templated>::Class_T > a1;
    A< TT_AF<Templated_alias>::Class_T > a2;
    a1 = a2;
    A< TT_AF<Templated2>::Class_T > a3;
    //a1 = a3;//no viable overloaded '='

}

Saída fornece:

0x600000014ba0
0x600000014ba0
0x0
---------------
0x600000014bb0
0x600000014bb0
0x0
---------------
0x0
0x0
0x600000014bc0

Depois de usar o truque acima. Encontrei problemas diferentes. Não posso ter certeza absoluta de que esteja relacionado, mas é muito provável. O compilador parece ter dificuldade para criar corretamente a 'tabela dinâmica'. Eu pedi esse problema emC ++ o que pode fazer type_info :: hash_code difere por dois (supostamente) mesmos objetos Pode ser ruim, mas por enquanto não recomendo usar o truque com o Clang 3.1.

questionAnswers(1)

yourAnswerToTheQuestion