【问题标题】:Forward declare a constexpr variable template前向声明一个 constexpr 变量模板
【发布时间】:2016-01-16 19:41:15
【问题描述】:

我尝试像这样转发声明constexpr 变量模板:

template<typename>
constexpr std::size_t iterator_category_value;

我们的目标是记录每个专业化都应该是constexpr,但我不得不承认我从未检查过它是否合法,g++ 对此很满意。但是,当我尝试用 clang++ 编译这个 spinnet 时,我得到了以下错误:

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 变量不是变量模板,因此变量模板上下文似乎是编译器不同意的原因。

【问题讨论】:

  • wg21.cmeerw.net/cwg/issue1712 的文本暗示您不能将其转发声明为constexpr,但我不太确定标准如何禁止它。变量模板在我看来不像是一个对象声明
  • OTOH,[dcl.dcl]p9 看起来很笼统,应该适用于变量模板(=> 变量模板是对象声明=> constexpr 需要初始化)
  • @dyp 顺便说一句,“现在”是什么意思?你不是在编译 Git 上当前可用的最新源代码吗?
  • @Columbo 不定期 :)
  • @dyp 是的,作为 object 声明 的变量模板声明对我来说并不是很明显,因此问题:/

标签: c++ language-lawyer c++14 constexpr variable-templates


【解决方案1】:

在 C++14 标准中,很明显需要初始化。从第 7.5.1 节第 9 段,

对象声明中使用的constexpr 说明符 将对象声明为 const。这样的对象应具有 字面量类型,应该被初始化。

至于“对象声明”的确切含义,第 7 节第 7 段指出:

如果 decl-specifier-seq 不包含 typedef 说明符, 该声明称为函数声明,如果 与名称关联的类型是函数类型,并且 否则为对象声明。

【讨论】:

    【解决方案2】:

    Clang 是正确的。变量模板的声明是一个对象声明([dcl.dcl]/9),因此它必须按照[dcl.constexpr]/9提供一个初始化器:

    对象声明中使用的constexpr 说明符声明 对象为const这样的对象 […] 应为 已初始化。

    不过,实际上没有办法“转发”首先将对象声明为constexpr;如果constexpr应用于变量的声明,它应该是一个定义([dcl.constexpr]/1)。

    【讨论】:

    • 只是一个包含讨论案例的代码。它包含constexpr 变量模板的前向声明,但编译得很好。
    • @Orient 您确实意识到您正在使用在这方面存在错误的编译器进行编译?
    • 是的,但我认为这种变化是在不久前引入的。大概是故意的吧。但也许不是。
    • @Orient 好吧,GCC 仅开始支持从 5.2 开始使用的所有功能,并且该版本已经伪编译得很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 2017-11-13
    相关资源
    最近更新 更多