23
struct A {       
    consteval A() {};
};

constexpr bool g() {
    auto a = new A;
    delete a;
    return true;
}

int main() {
    static_assert(g());
}

https://godbolt.org/z/jsq35WxKs

GCC 和 MSVC 拒绝该程序,ICC 和 Clang 接受它:

///MSVC: 
<source>(6): error C7595: 'A::A': call to immediate function is not a constant expression
Compiler returned: 2

//GCC:
<source>: In function 'constexpr bool g()':
<source>:6:18: error: the value of '<anonymous>' is not usable in a constant expression
    6 |     auto a = new A;
      |                  ^
<source>:6:18: note: '<anonymous>' was not declared 'constexpr'
<source>:7:12: error: type '<type error>' argument given to 'delete', expected pointer
    7 |     delete a;
      |            ^
Compiler returned: 1

虽然,替换new Anew A()导致 GCC 也接受该程序(但两者都不new A{}是)。


至少进行以下更改之一会导致所有四个编译器都接受该程序:

  1. 替换constevalconstexpr

  2. 替换constexprconsteval

  3. 代替

    auto a = new A;
    delete a;
    

    auto alloc = std::allocator<A>{};
    auto a = alloc.allocate(1);
    std::construct_at(a);
    std::destroy_at(a);
    alloc.deallocate(a, 1);
    

    A a;, 有auto&& a = A{};或 有A{};

只有例外:

  • 带有 libstdc++ 的 Clang 主干std::allocator似乎由于不相关的错误而无法使用该版本进行编译。对于 Clang 13 或 libc++,它也被接受。

    In file included from <source>:1:
    In file included from [...]/memory:78:
    [...]/shared_ptr_atomic.h:459:14: error: missing 'typename' prior to dependent type name '_Atomic_count::pointer'
      static _Atomic_count::pointer
    
  • std::allocator只要consteval构造函数上有, MSVC 就会拒绝该版本:

    error C7595: 'A::A': call to immediate function is not a constant expression
    <source>(10): note: see reference to function template instantiation '_Ty *std::construct_at<_Ty,,void>(_Ty *const ) noexcept(false)' being compiled
            with
            [
                _Ty=A
            ]
    

完全替换或删除调用似乎static_assert(g());g()这些结果没有任何影响。


哪些编译器是正确的,如果原始编译器格式不正确,为什么只不允许使用限定符和构造方法的特定组合?


受到此答案下的评论的启发。

4

0 回答 0