[英]How to define constructor of fully-specialized class within another class template
我有一個包含另一個類模板的類模板,內部模板有一個顯式的特化:
template <typename Outer>
struct ContainingClass {
template <typename T>
struct Rule {
Rule(T value);
// ... other members ...
};
template <>
struct Rule<void> {
Rule();
// ... different members than the non-void Rule<T> ...
};
};
我已經為泛型和專用Rule
定義了構造函數:
template <typename Outer>
template <typename T>
ContainingClass<Outer>::Rule<T>::Rule(T value) { }
template <typename Outer>
ContainingClass<Outer>::Rule<void>::Rule() { }
但Clang不喜歡專門類的構造函數:
error: nested name specifier 'ContainingClass<Outer>::Rule<void>::' for declaration does not refer into a class, class template or class template partial specialization
ContainingClass<Outer>::Rule<void>::Rule() { }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
我對此感到困惑,因為它“引用” ContainingClass<Outer>
,它是一個類( ContainingClass
類模板的一個實例)。 我懷疑我需要在語法中改變一些東西,但目前還不清楚是什么。 我該如何定義這個構造函數?
(如果我刪除ContainingClass
並將Rule
放在命名空間范圍內,它可以工作,但我需要在Rule
中有其他依賴於Outer
類型的東西。我可以給Rule
自己的Outer
模板參數,但這會讓事情變得更加尷尬使用這個類的代碼,所以我想盡可能避免它。我知道我可以在Rule
類體內定義構造函數內聯,但我想理解為什么單獨的定義不起作用。)
如果它很重要,我在Ubuntu 19.04中使用Clang 8.0,在Mac上使用Apple的“clang-1001.0.46.4”。 (我也嘗試過Ubuntu的GCC 8.3,但由於GCC錯誤#85282 - 在非命名空間作用域中顯式特化“在struct Rule<void>
本身的定義上,它在另一個地方失敗了。)
編輯澄清:我的錯誤不是在ContainingClass
具有template <> struct Rule<void>
。 這是C ++ 14限制( 缺陷CWG 727 )的主題,它通過添加虛擬模板參數來解決,因此模板只是部分而不是完全專用。 我相信在C ++ 17中已經取消了限制,並且Rule
類的特化本身在Clang中運行良好(盡管GCC有bug)。 所以我認為虛擬參數解決方法在這里不是正確的解決方案 - 但請告訴我,如果我錯了,並且在C ++ 17中仍存在限制。
您不能在命名空間作用域聲明模板的模板成員的特化成員。
為了避免這種限制,您可以使用c ++ 14及更早版本所必需的解決方法,其中包括使用部分特化而不是完全特化:
template <typename Outer>
struct ContainingClass {
template <typename T,class=void>
struct Rule {
Rule(T value);
// ... other members ...
};
template <class U>
struct Rule<void,U> {
Rule();
// ... different members than the non-void Rule<T> ...
};
};
template <typename Outer>
template <typename T, typename U>
ContainingClass<Outer>::Rule<T,U>::Rule(T value) { }
template <typename Outer>
template <typename U>
ContainingClass<Outer>::Rule<void,U>::Rule() { }
在C ++ 17中,仍然無法在命名空間范圍內聲明(模板的)類模板的特化成員(參見[temp.expl.spec] / 17) 。 C ++ 14標准中存在相同的段落。
使用C ++ 17改變的是我們可以在封閉類模板定義中聲明成員的特化:
應在包含專用模板的命名空間中聲明顯式特化。[...]
可以在可以定義相應主模板的任何范圍內聲明顯式特化。[...]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.