奇怪的constexpr类型错误

Weird constexpr typeid errors

本文关键字:类型 错误 constexpr      更新时间:2023-10-16

给定代码

#include <typeinfo>
#include <type_traits>
struct A {};
struct B {};
static_assert(&typeid(A), ""); // Fine
static_assert(&typeid(B), ""); // Fine
static_assert(&typeid(A) != nullptr, ""); // Fine
static_assert(&typeid(B) != nullptr, ""); // Fine
constexpr auto const * tA = &typeid(A);
constexpr auto const * tB = &typeid(B);
using T = decltype(tA);
using T2 = decltype(tB);
static_assert(std::is_same<T, T2>::value, ""); // Fine, identical types!
static_assert(tA == tA, ""); // Fine (comparing values of identical type)
static_assert(tB == tB, ""); // Fine (comparing values of identical type)
static_assert(tA != tB, ""); // Error: comparing values of identical type
                             //        suddenly not constexpr?

我得到Clang的以下错误:

$ clang++ -std=c++1z test.cpp -o test
test.cpp:19:18: error: static_assert expression is not an integral constant expression
static_assert(tA != tB, ""); // Error: comparing values of identical type not constexpr?
            ~~~^~~~~
1 error generated.

和GCC:

$ g++-6.3.0 -std=c++1z test.cpp -o test
test.cpp:19:1: error: non-constant condition for static assertion
static_assert(tA != tB, ""); // Error: comparing values of identical type not constexpr?
^~~~~~~~~~~~~
test.cpp:19:18: error: '(((const std::type_info*)(& _ZTI1A)) != ((const std::type_info*)(& _ZTI1B)))' is not a constant expression
static_assert(tA != tB, ""); // Error: comparing values of identical type not constexpr?
            ~~~^~~~~

对于tAtB,我是否使用void而不是auto都没有关系。只有GCC-s输出略有变化:

$ g++-6.3.0 -std=c++1z test.cpp -o test
test.cpp:19:5: error: non-constant condition for static assertion
    static_assert(tA != tB, ""); // Error: comparing values of identical type not constexpr?
    ^~~~~~~~~~~~~
test.cpp:19:22: error: '(((const void*)(& _ZTI1A)) != ((const void*)(& _ZTI1B)))' is not a constant expression
    static_assert(tA != tB, ""); // Error: comparing values of identical type not constexpr?
                ~~~^~~~~

有人能解释为什么只有最后一个static_assert不能编译,而其他的编译和通过?

编译器似乎遵循[expr.const]/(2.20):

本;关系(5.9)或相等(5.10)操作符,其结果未指定;

也许指向两个这样的对象的指针不一定指定为不相等,但在我看来,这似乎是一个错误。