Clang,std :: next,libstdc ++和constexpr-ness

时间:2018-04-18 09:09:32

标签: c++ c++17 constexpr static-assert

请使用以下代码:

#include <array>

constexpr std::array<int, 10> a{};
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);

使用-std=c++17 GCC可以完美地编译它,但Clang抱怨表达式不是一个完整的常量表达式。看起来问题是关于std::next,但是,在C ++ 17中应该是constexpr

然而,std::next在std库中,而不在编译器本身中,因此有一些奇怪的事情发生。只是为了让事情变得更好,如果你将-stdlib=libc++传递给Clang,那么这个例子会很好地编译。

发生了什么事?谁错了,谁是对的?

修改

这个问题似乎与使用Godbolt内的GCC 7.2的工具链相关。如果将--gcc-toolchain=/opt/compiler-explorer/gcc-snapshot参数添加到命令行,一切都可以正常运行。 (感谢@einpoklum向godbolt报告了这个问题 - 我的速度较慢;)

修改

对于那些认为旧编译器应该符合实际标准的人,不好意思说这个考虑是没有意义的。我在谈论GCC和Clang的最新版本。并且这个问题可以通过两者的主干版本重现。较旧的编译器与此问题无关(相反,MSVC行为会很有趣)。

2 个答案:

答案 0 :(得分:3)

在Wandbox中编译

#include <array>

int main()
 {
   constexpr std::array<int, 10> a{};
   static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
 }

使用clang ++ 4.0.1和命令行

clang++ prog.cc -Wall -Wextra -std=c++1z

我收到错误

prog.cc:6:18: error: static_assert expression is not an integral constant expression
   static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:6:18: note: non-constexpr function 'next<const int *>' cannot be used in a constant expression
/opt/wandbox/clang-4.0.1/include/c++/v1/iterator:599:1: note: declared here
next(_InputIter __x,
^
1 error generated.

但是使用

编译clang ++ 5.0.0(或6.0.0或7.0.0 HEAD)
clang++ prog.cc -Wall -Wextra -std=c++17

因此,对于clang ++ 4.0.1(和/或clang ++使用的库)中的C ++ 17似乎缺乏支持,在以下版本中进行了更正。

- 编辑 -

gobold 中的clang ++ 5.0.0和clang ++ 6.0.0确认了问题(参见einpoklum的回答)。

所以我认为问题是libstdc ++的版本:似乎 gobold 正在使用一个版本(我认为是较旧版本)std::next()未被定义为{ {1}} wandbox 使用constexprstd::next()的版本。

答案 1 :(得分:2)

使用GodBolt.org上的Clang 6.0.0和5.0.0版本,您的代码确实fail to compile。但是 - 在我的系统上使用clang 5.0.0-3(Lubuntu 17.10),它似乎没有错误编译。

这是奇怪的行为。所以,也许不是你问题的最佳答案,但面对这样的事情,我会在bugs.llvm.org报告,看看铿锵/ LLVM开发人员说的话。