C ++ - dynamisches Downcasting auf Klassenvorlagen mit Vorlagenvorlagenparametern als Klassenvorlage oder Aliasvorlage

ch hoffe der Titel macht Sinn. Ich vermisse wahrscheinlich den Wortschatz, um ihn richtig auszudrücken.

Nun, ein Beispiel wird wahrscheinlich klarer sein.

Problem für mich ist: dynamisches Downcasting gibt zur Laufzeit in einigen der folgenden Fälle 0 zurück (in Kommentaren geschrieben). Ich würde gerne wissen, ob es ein korrektes Verhalten ist (unter Verwendung von C ++ 11), auch warum und was ich tun kann, damit es funktioniert. Anscheinend werden Templated und A :: A_templated als unterschiedliche Klassen behandelt, obwohl sie mit dem Alias "using" als identisch definiert wurden. Das Problem tritt bei einem einfachen Typedef-Alias nicht auf.

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 !


}

Ich schlage einen anderen Weg vor, um das Problem zu sehen, dies ist wahrscheinlich klarer. Ich stelle es gegenüber, nachdem ich versucht habe, das obige Beispiel zu vermeiden. Das folgende Beispiel sagt im Grunde das aus, worauf Bogdan hingewiesen hat. Ich finde es sehr frustrierend, dass der Compiler Templated with Templated_alias nicht auflösen kann. Ich frage mich, ob es eine Kompilierungsoption gibt, die eine Art Force-Typ durch Vorlagen-Aliase auflösen kann.

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
}

Danke an Bogdans Trick, und nach ein wenig Nasenbluten habe ich es geschafft, eine Lösung zu finden. Die Idee ist, eine Klasse zu erstellen, die potenzielle Aliase von Vorlagenklassen 'filtert'. Es muss eine Spezifikation pro Vorlagenklasse 'gefiltert' werden. Der Hauptnachteil der Methode besteht darin, dass die Filterung überall dort verwendet werden muss, wo Vorlagenklassen als Vorlagenparameter verwendet werden, um konsistent zu sein.

//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 '='

}

Output gibt:

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

Nachdem Sie den obigen Trick angewendet haben. Ich bin auf verschiedene Probleme gestoßen. Ich kann nicht sicher sein, ob es verwandt ist, aber es ist sehr wahrscheinlich. Der Compiler scheint Schwierigkeiten zu haben, die 'dynamische Tabelle' korrekt zu erstellen. Ich habe nach diesem Problem gefragt bei C ++ was type_info :: hash_code machen kann unterscheidet sich für zwei (angeblich) gleiche Objekte Kann mein schlechtes sein, aber im Moment würde ich nicht empfehlen, den Trick mit Clang 3.1 zu verwenden.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage