タイトルが意味をなすことを願っています。正確に表現するための語彙が欠けているのでしょう。
まあ、例はおそらくより明確になるでしょう。
私の問題は次のとおりです。動的ダウンキャストは、次のケースのいくつかで実行時に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 !
}
問題を確認する別の方法を提案します。これはおそらくより明確です。上記の例を回避しようとした後、私はそれに直面しています。次の例は、基本的に Bogdan が指摘したことを示しています。コンパイラが Templated_alias を使用して Templated を解決できないという事実は、非常にイライラさせられます。テンプレートエイリアスを介して強制的に型を解決できるコンパイルオプションが存在するかどうか疑問に思っています。
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
}
ボグダンのトリックのおかげで、少し鼻血が出た後、何とか解決策を見つけることができました. アイデアは、テンプレート クラスの潜在的なエイリアスの「フィルタリング」を担当するクラスを構築することです。「フィルタリング」する必要があるテンプレート クラスごとに 1 つの仕様が必要です。この方法の主な欠点は、一貫性を保つために、テンプレート クラスがテンプレート パラメータとして使用されるすべての場所でフィルタリングを使用する必要があることです。
//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
上記のトリックを使用した後。私はさまざまな問題に遭遇しました。絶対に関係があるとは断言できませんが、その可能性は非常に高いです。コンパイラは「動的テーブル」を正しく構築するのに苦労しているようです。type_info::hash_code を 2 つの (おそらく) 同じオブジェクトで異なるものにすることができる C++でこの問題を求めました 。