【问题标题】:constexpr std::array with static_assert带有 static_assert 的 constexpr std::array
【发布时间】:2014-11-04 17:12:51
【问题描述】:
#include <iostream>
#include <array>

int main(int argc, char **argv) {
    constexpr const std::array<int, 2> arr {{ 0, 1 }};
    constexpr const int arr2[] = { 0, 1};

    static_assert(arr[0] == arr2[0], "asdf");
    static_assert(arr[1] == arr2[1], "asdfasdf");

    return 0;
}

当使用gcc 4.8.24.9.1 使用g++ test.cpp --std=c++11 编译时,编译成功。 然而,当使用clang 3.43.5 使用clang++ test.cpp --std=c++11 编译时,编译失败:

test.cpp:8:16: error: static_assert expression is not an integral constant expression
        static_assert(arr[0] == arr2[0], "asdf");
                      ^~~~~~~~~~~~~~~~~
test.cpp:8:16: note: non-constexpr function 'operator[]' cannot be used in a constant expression

所以我的问题是,在符合 C++11 的意义上,哪个编译器是“正确的”?而且,如果clang 是正确的,那么为什么std::array 的operator[] 不能使用constexpr?这难道不是std::array 应该帮助解决的问题之一吗?

【问题讨论】:

    标签: c++ c++11 constexpr static-assert stdarray


    【解决方案1】:

    看起来clang 是正确的,operator [] 不是 C++11 中的 constexpr,而是 C++14 中的 constexpr

    constexpr const_reference operator[]( size_type pos ) const; (since C++14)
    

    所以使用-std=c++14 编译应该可以工作(see it live)。

    C++11 draft standard 部分23.3.2.1 类模板数组概述 有以下operator []

    reference operator[](size_type n);
    const_reference operator[](size_type n) const;
    

    C++14 draft standard 具有以下内容:

    reference operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    ^^^^^^^^^
    

    更新

    C++11 之后的标准草案N3485,包含对 C++11 的增强修复。它包含operator []constexpr 版本。如果这是缺陷报告的一部分,那么 gcc 将是正确的,考虑到 clang 3.6.0 也接受 C++11 模式下的程序,这似乎是合理的。

    更新 2

    我找到了介绍更改的文档N3470,由于我找不到有关此特定问题的任何缺陷报告,因此这似乎是一种增强,因此不应成为 C++11 的一部分。

    【讨论】:

    • 在 C++11 中,可以将 array::operator[] const 声明为 constexpr,但委员会直到 C++14 才开始这样做。在 C++14 中,可以将 array::operator[] 声明为 constexpr...
    • @Casey 我找到了将更改引入N3485 的文档,我将其添加到我的答案中。据我了解,如果它被认为是一个缺陷,它应该在 C++11 模式下被允许,否则不允许。不过,该文件并未对此进行说明。
    • 我主要是在取笑标准:库更改通常落后于核心,因为核心喜欢在最后一刻进行更改,而没有给库足够的时间做出反应。我相信 N3470 中添加的constexpr 是一种增强,因为涉及constexprarray 的唯一缺陷报告是LWG DR 720,它不涉及operator[]
    • 用 --std=c++1y 在 clang 3.4 中编译 3.5 和 --std=c++14 似乎确实像我预期的那样工作。
    猜你喜欢
    • 1970-01-01
    • 2020-03-22
    • 2019-01-31
    • 1970-01-01
    • 2016-11-13
    • 2020-02-07
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多