提前声明一个constexpr变量模板

12

我尝试像这样前置声明一个constexpr变量模板:

template<typename>
constexpr std::size_t iterator_category_value;

目标是记录每个特化版本都应该是 constexpr,但我必须承认我从未检查过它是否合法,g++却没有报错。然而,当我试图使用clang++编译这个代码片段时,我遇到了以下错误:

error: default initialization of an object of const type 'const std::size_t' (aka 'const unsigned long')
    constexpr std::size_t iterator_category_value;
                          ^
                                                  = 0
错误是有道理的,移除constexpr后错误消失了,所以这不是一个真正的问题。然而,现在我很好奇:标准是否允许为变量模板进行这样的constexpr前向声明,或者这是非法的?g++和clang++似乎存在分歧,如果需要的话,我想知道应该向哪里提交错误报告。
它们两个都会抱怨前置声明的constepxr变量不是变量模板,因此变量模板上下文似乎是编译器产生分歧的原因。

http://wg21.cmeerw.net/cwg/issue1712 的文本意味着您不能将其前向声明为constexpr,但我不太确定标准如何禁止它。 对我来说,变量模板看起来并不像对象声明 - dyp
另一方面,[dcl.dcl]p9似乎非常通用,应该适用于变量模板(=>变量模板是对象声明=>constexpr要求初始化) - dyp
@dyp 顺便问一下,“现在”是什么意思?你不是正在编译Git上当前可用的最新源代码吗? - Columbo
@Columbo 不是经常 :) - dyp
@dyp 是的,变量模板声明作为一个对象声明对我来说并不是很明显,所以才会问这个问题 :/ - Morwenn
2个回答

10
在C++14标准中,初始化是必需的。从第7.5.1节第9段可以看出,一个对象声明中使用的constexpr指定符将该对象声明为const。这样的对象应该具有字面类型并且需要被初始化。关于“对象声明”的确切含义,在第7节第7段中有解释:如果decl-specifier-seq不包含typedef指定符,则如果与名称相关联的类型是函数类型,则声明称为函数声明,否则是对象声明。

10
Clang是正确的。变量模板的声明是一个对象声明([dcl.dcl]/9),因此必须根据[dcl.constexpr]/9提供初始化程序:
“在对象声明中使用的constexpr说明符将对象声明为const。这样的对象[...]必须被初始化。”
实际上,没有办法"向前"声明一个对象作为constexpr;如果将constexpr应用于变量的声明,则它应该是一个定义([dcl.constexpr]/1)。

最近有什么改变了吗?(http://coliru.stacked-crooked.com/a/cb1d8ebe90a2bc11) - Tomilov Anatoliy
这只是一个包含讨论案例的代码。它包含了constexpr变量模板的前向声明,但编译正常。 - Tomilov Anatoliy
@Orient 你意识到你正在使用这方面存在缺陷的编译器进行编译吗? - Columbo
是的,但我认为这个变化是最近引入的。可能是有意为之,但也可能不是。 - Tomilov Anatoliy
@Orient Well,GCC只从5.2版本开始支持所有使用的功能,并且该版本已经可以虚假编译这个程序。 - Columbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接