[英]Template partial specialization
有人會知道根據什么規則下面的代碼不能編譯嗎?
template <class T>
struct B
{
typedef T type;
};
template<class T>
struct X
{
};
template<class T>
struct X<B<T>::type*>//HERE I'M PARTIALLY SPECIALIZING (WELL, TRYING TO...)
{
};
請參閱代碼中的注釋。
你認為這將如何運作? 編譯器將查看某處是否有一個類 T 對您的類具有 typedef“類型”?
它只是不會。 盡管它是一個指針。
請記住,您的 B 模板可能在某些地方是專門化的,因此類型並不總是 T*,但它無法通過逆向工程推斷它。
對於那些不完全理解我的答案的人,您要求編譯器做的是找到一個類 U ,使得 B::type 是您作為參數傳入的類。
class Foo;
class Bar;
template<> struct B<Foo>
{
typedef int type;
};
template<> struct B<Bar>
{
typedef int type;
};
X<int*> // ambiguous, T is Foo or Bar?
很難確切地知道你為什么要做你現在的樣子。 您可以對所有指針進行部分特化,然后對特定指針進行完全特化,這可以根據另一個模板來實現。
您需要使用typename
關鍵字,
template<class T>
struct X<typename B<T>::type*>
{
};
這是因為B<T>::type
是一個從屬名稱。 所以typename
是必需的!
--
編輯:
即使在放置typename
之后,它也沒有編譯。 我認為這是因為從X<U>
中推斷出B<T>
中的T
類型對於編譯器來說是困難的,或者可能是不可能的。 所以我相信它的非推斷上下文。
請參閱此處的類似示例和討論:
但是,如果您將專業化更改為此:
template<class T>
struct X<B<T> >
{
};
然后它變成可演繹的上下文,因此會編譯。
假設您已經按照 Nawaz 的建議添加了typename
。
該問題在您遇到的錯誤消息中得到了確切的解釋:“模板參數在偏特化B<T>::type*
中不可推導。問題是B<T>::type
和T
對於所有類型都完全相同T
. 考慮以下示例:
class MyClass1 {};
typedef typename B<MyClass>::type MyClass2; //(*)
X<MyClass*> obj1;
X<MyClass2*> obj2;
行(*)
的結果是類型 MyClass2 ,它本質上是MyClass1
。 所以, obj1
和obj2
應該是同一個類的對象。 現在,他們應該使用哪個版本的模板X
?
如果您期望X
的專用版本,請告訴我如果刪除行(*)
答案是否應該相同(顯然obj2
也是如此)。 仍然obj1
應該是X
的專用版本,因為行(*)
與它無關。
但是現在我們希望編譯器能夠檢測到某些類型可能被聲明為B<T>::type
,盡管我們從未這樣做過。 我們希望編譯器驗證所有可能的模板實例化,以檢查其中一個是否沒有奇怪的 typedef。
我希望這能闡明為什么編譯器無法處理這種專業化。
可能有幫助的替代方案
我相信你的問題可以通過創建一個特征類來明確標記應該以特殊方式處理的類型來解決。 像這樣的東西:
template <bool v>
struct boolean_value {
static const bool value=v;
};
template <typename T>
struct is_my_interesting_type : public boolean_value<false> {};
class MyClass {
...
};
template <>
struct is_my_interesting_type<MyClass> : public boolean_value<true> {};
template <typename T, bool special>
class InternalX {
... //generic version of your template X
};
template <typename T>
class InternalX<T,true> {
... //special version of your template X
};
template <typename T>
class X : public InternalX<T,is_my_interesting_type<T>::value> {};
此外,您可能會對它在 boost 庫中的完成方式感興趣,特別是Boost.Type_Traits
“參數列表不能與非特化參數列表相同(它必須特化某些東西)”請參閱en.cppreference.com 上的 partial_specialization
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.