继承嵌套模板的特化 class
Specialization of inherited nested template class
以下源码来自:
Understanding partial specialization of inherited nested class templates
#include <type_traits>
struct Base
{
template<class U, class _ = void> struct Inner: std::true_type {};
template<class _> struct Inner<char, _>: std::false_type {};
};
struct Derived : Base
{
};
template<class _> struct Derived::Inner<int, _>: std::false_type {};
我有一个关于专门化继承 class 的问题,所以我用谷歌搜索,找到了上面的问题。上面问题中的源代码编译w/o any proble in gcc/clang,但是msvc拒绝编译它,发出C2427(见https://msdn.microsoft.com/en-us/library/10het5hx.aspx)。
上面的情况(specify the nested template class of a non-template class)和https://msdn.microsoft.com/en-us/library/10het5hx.aspx描述的情况(定义嵌套的non-template class 的模板 class),我认为。
msvc 与 gcc/clang 哪个是错误的?或者只是标准不清楚,无法指定此行为?
我希望 msvc 是错误的...
Clang 和 GCC 是错误的,而 MSVC 和 EDG 拒绝该部分专业化定义是正确的。
偏特化本身就是一个模板,class 模板定义是根据 class 定义在句法上构造的(在语法术语中,class-说明符)。在这样的定义中,Derived::Inner<int, _>
是一个 class-head-name,Derived::
是一个 nested-name-specifier 。
[9p11] 在标准中说:
If a class-head-name contains a nested-name-specifier, the
class-specifier shall refer to a class that was previously declared
directly in the class or namespace to which the nested-name-specifier
refers, or in an element of the inline namespace set (7.3.1) of that
namespace (i.e., not merely inherited or introduced by a
using-declaration), and the class-specifier shall appear in a
namespace enclosing the previous declaration. [...]
因此,您必须使用 Base::Inner<int, _>
。
如评论中所述,上面的引用也适用于 class 模板显式专业化定义(它们的语法生成最终也使用 class-head-name).
以下内容并不直接适用于您的示例,但我发现值得一提。
请注意,上面的引用指的是 class 模板(或显式特化)定义,而不是
等声明
template<class _> struct Derived::Inner<int, _>;
在句法上,struct Derived::Inner<int, _>
中有一个 elaborated-type-specifier,上面的段落对其不适用。因此,标准措辞在技术上允许此类声明。
这似乎不是疏忽:上面的措辞是由 DR284 的决议引入的,其中包括评论:
The sentiment was that this should be required on class definitions,
but not on elaborated type specifiers in general (which are
references, not declarations). [...]
提议的决议包括详尽的类型说明符,但这些已从最终措辞中删除。
但是,MSVC 和 EDG 都不接受此类声明(坦率地说,如果他们接受,我会觉得很困惑)。 DR 中的评论似乎表明其意图是仅允许 elaborated-type-specifiers 而不是声明,但看起来这并没有反映在措辞中(a我认为是标准错误)。
以下源码来自: Understanding partial specialization of inherited nested class templates
#include <type_traits>
struct Base
{
template<class U, class _ = void> struct Inner: std::true_type {};
template<class _> struct Inner<char, _>: std::false_type {};
};
struct Derived : Base
{
};
template<class _> struct Derived::Inner<int, _>: std::false_type {};
我有一个关于专门化继承 class 的问题,所以我用谷歌搜索,找到了上面的问题。上面问题中的源代码编译w/o any proble in gcc/clang,但是msvc拒绝编译它,发出C2427(见https://msdn.microsoft.com/en-us/library/10het5hx.aspx)。
上面的情况(specify the nested template class of a non-template class)和https://msdn.microsoft.com/en-us/library/10het5hx.aspx描述的情况(定义嵌套的non-template class 的模板 class),我认为。
msvc 与 gcc/clang 哪个是错误的?或者只是标准不清楚,无法指定此行为?
我希望 msvc 是错误的...
Clang 和 GCC 是错误的,而 MSVC 和 EDG 拒绝该部分专业化定义是正确的。
偏特化本身就是一个模板,class 模板定义是根据 class 定义在句法上构造的(在语法术语中,class-说明符)。在这样的定义中,Derived::Inner<int, _>
是一个 class-head-name,Derived::
是一个 nested-name-specifier 。
[9p11] 在标准中说:
If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (7.3.1) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. [...]
因此,您必须使用 Base::Inner<int, _>
。
如评论中所述,上面的引用也适用于 class 模板显式专业化定义(它们的语法生成最终也使用 class-head-name).
以下内容并不直接适用于您的示例,但我发现值得一提。
请注意,上面的引用指的是 class 模板(或显式特化)定义,而不是
等声明template<class _> struct Derived::Inner<int, _>;
在句法上,struct Derived::Inner<int, _>
中有一个 elaborated-type-specifier,上面的段落对其不适用。因此,标准措辞在技术上允许此类声明。
这似乎不是疏忽:上面的措辞是由 DR284 的决议引入的,其中包括评论:
The sentiment was that this should be required on class definitions, but not on elaborated type specifiers in general (which are references, not declarations). [...]
提议的决议包括详尽的类型说明符,但这些已从最终措辞中删除。
但是,MSVC 和 EDG 都不接受此类声明(坦率地说,如果他们接受,我会觉得很困惑)。 DR 中的评论似乎表明其意图是仅允许 elaborated-type-specifiers 而不是声明,但看起来这并没有反映在措辞中(a我认为是标准错误)。