我有一个类模板,其中包含另一个类模板,内部模板具有显式特化:
我已经为通用和专用的
我对此感到困惑,因为它“引用”了
(如果我删除
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和苹果的"clang-1001.0.46.4"。 (我还尝试过Ubuntu的GCC 8.3,但由于GCC bug #85282 - 在struct Rule<void>
本身的定义中在非命名空间范围内显式特化 - 在不同的位置失败。)
ContainingClass
中有template <> struct Rule<void>
特化。这是C++14限制的主题(defect CWG 727),通过添加虚拟模板参数来解决,使得模板只部分而不是完全特化。我相信这种限制已经在C++17中解除了,在Clang中,Rule
类本身的特化工作正常(尽管GCC存在缺陷)。所以我认为虚拟参数解决方法在这里不是正确的解决方法-但请告诉我如果我错了,C++17中仍然存在这方面的限制。