2014-11-04 88 views
10
#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然而编译,编译失败:constexpr的std ::阵列static_assert

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应该帮助解决的事情之一吗?

回答

9

看起来clang是正确的,operator []是不是在C++ 11 constexpr但处于constexpr C++ 14

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

-std=c++14所以应编制工作,虽然(see it live)。

C++11 draft standard23.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的增强功能。它包含一个constexpr版本的operator []。如果这是缺陷报告的一部分,那么gcc将是正确的,这似乎是合理的,因为clang 3.6.0也接受C++ 11模式下的程序。

更新2

我发现,引入的变化,N3470文档,因为我无法找到关于这个问题的任何缺陷报告,然后这似乎是一个增强,因此不应该是C++的一部分+11。

+0

在C++ 11中,将'array :: operator [] const'声明为'constexpr'已成为可能,但委员会在C++ 14之前没有考虑这么做。在C++ 14中,将'array :: operator []'声明为'constexpr'成为可能...... – Casey 2014-11-04 18:12:54

+1

@Casey我找到了将变更引入'N3485'的文档,我将其添加到我的答案中。据我了解,如果它被认为是一个缺陷,它应该允许在C + + 11模式,但否则不应该。尽管如此,该文件并没有阐明。 – 2014-11-04 18:14:43

+1

我大部分时间都喜欢这个标准:库变化通常落后于核心,因为核心喜欢在最后一刻进行更改,而没有给库提供足够的时间来做出反应。我相信在N3470中增加constexpr是一个增强,因为涉及'constexpr'的'array'的唯一缺陷报告是[LWG DR 720](http://www.open-std.org/jtc1/sc22 /wg21/docs/lwg-defects.html#720),它不涉及'operator []'。 – Casey 2014-11-04 18:27:42