Динамическое преобразование C ++ в шаблон класса с параметром шаблона template, являющимся шаблоном класса или шаблоном псевдонимов.

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

Ну, пример, вероятно, будет более понятным.

Проблема для меня заключается в следующем: динамическое снижение рейтинга возвращает 0 во время выполнения в некоторых из следующих случаев (записано в комментариях). Я хотел бы знать, правильное ли это поведение (с использованием C ++ 11), а также почему и что я могу сделать, чтобы это работало. Очевидно, Templated и A :: A_templated обрабатываются как разные классы, несмотря на то, что они определены как идентичные с использованием псевдонима "using". Проблема не появляется для простого псевдонима 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 !


}

Я предлагаю другой способ увидеть проблему, это, вероятно, более ясно. Я сталкиваюсь с этим после попытки избежать примера выше. Следующий пример в основном говорит, на что указал Богдан. Я нахожу очень неприятным тот факт, что компилятор не может разрешить Templated с помощью Templated_alias. Мне интересно, существует ли опция компиляции, которая может сортировать принудительные типы с помощью псевдонимов шаблонов.

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
}

Благодаря уловке Богдана и после небольшого кровотечения из носа мне удалось найти какое-то решение. Идея состоит в том, чтобы создать класс, отвечающий за «фильтрацию» потенциальных псевдонимов шаблонных классов. Требуется одна спецификация на класс шаблона, который необходимо «отфильтровать». Основным недостатком метода является то, что фильтрация, таким образом, должна использоваться везде, где классовые шаблоны используются в качестве параметров шаблона, чтобы быть согласованными.

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

}

Выход дает:

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

После использования вышеуказанного трюка. Я столкнулся с разными проблемами. Не могу быть абсолютно уверен, что это связано, но это очень вероятно. Компилятор, кажется, изо всех сил пытается правильно построить «динамическую таблицу». Я спросил об этой проблеме вC ++, что может сделать type_info :: hash_code разным для двух (предположительно) одинаковых объектов Может быть, это плохо, но сейчас я бы не советовал использовать трюк с Clang 3.1.

Ответы на вопрос(1)

Ваш ответ на вопрос