gpt4 book ai didi

c++ - 如何在另一个类模板中定义完全专用类的构造函数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:33:10 25 4
gpt4 key购买 nike

我有一个包含另一个类模板的类模板,并且内部模板具有显式特化:

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 bug #85282 而在不同的地方失败了——struct Rule<void> 本身定义中的“非命名空间范围内的显式特化”。)

编辑澄清:我的错误不是关于在 template <> struct Rule<void> 中有 ContainingClass 特化。这是 C++14 限制 ( defect CWG 727 ) 的主题,它通过添加虚拟模板参数来解决,因此模板只是部分专用的,而不是完全专用的。我相信 C++17 中已经取消了限制,并且 Rule 类本身的特化在 Clang 中工作正常(尽管 GCC 有错误)。所以我认为虚拟参数变通方法在这里不是正确的解决方案——但如果我弄错了请告诉我,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 .同款存在in the C++14 standard .

C++17 的变化是我们可以在封闭类模板定义中声明成员的特化:

An explicit specialization shall be declared in a namespace enclosing the specialized template.[...]

An explicit specialization may be declared in any scope in which the corresponding primary template may be defined.[...]

关于c++ - 如何在另一个类模板中定义完全专用类的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56892367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com