Clang, std::next, libstdc++ and constexpr-ness
Clang, std::next, libstdc++ and constexpr-ness
采用以下代码:
#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,该示例可以完美编译。
这是怎么回事?谁错谁对?
编辑
这个问题似乎与 clang 在 godbolt 中针对 GCC 7.2 的工具链有关。如果将--gcc-toolchain=/opt/compiler-explorer/gcc-snapshot
参数添加到命令行,一切都可以完美运行。(感谢@einpoklum向 godbolt 报告问题的人 - 我;)
慢了)编辑
对于每个认为旧编译器应该为实际标准工作的人,很抱歉说这种考虑毫无意义。我说的是GCC和Clang的最新版本。并且两者的中继版本都可以重现该问题。较旧的编译器与此问题无关(相反,MSVC 行为会很有趣)。
在 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 的支持似乎很低,在以下版本中得到了纠正。
--编辑--
问题已确认(参见 einpoklum 的答案)适用于gobold中的 clang++ 5.0.0 和 clang++ 6.0.0。
所以我想问题是libstdc++的版本:似乎gobold正在使用一个版本(我想是一个较旧的版本),其中std::next()
没有定义为constexpr
wandbox正在使用std::next()
constexpr
的版本。
使用 Clang 6.0.0 和 5.0.0 版本 GodBolt.org,您的代码确实无法编译。但是 - 在我的系统(Lubuntu 17.10)上使用 clang 5.0.0-3,它似乎编译没有错误。
这是奇怪的行为。所以,也许不是你问题的最佳答案,但面对这样的事情,我会在 bugs.llvm.org 上报告,看看clang/LLVM开发人员怎么说。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 多成员Constexpr结构初始化
- 条件constexpr函数
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- Visual C++ constexpr Hints
- 如何确认我的constexpr表达式实际上已经在编译时执行
- Constexpr and SSE intrinsics
- C++ standard: ODR and constexpr std::string_view
- Clang, std::next, libstdc++ and constexpr-ness
- 海湾合作委员会和Clang在lambda的constexpr-ness上存在分歧?
- google-test and static constexpr member
- lambda内部捕获的constexpr变量失去了其constexpr-ness
- constexpr and virtual
- C++17 make_optional constexpr-ness
- 非成员函数 begin()/cbegin() 及其 constexpr-ness
- constexpr, static_assert, and inlining
- constexpr and bizzare error
- constexpr and ODR
- constexpr if and static_assert
- std::max() and std::min() not constexpr