标签: consteval

constexpr 上下文中带有 consteval 构造函数的新表达式

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

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

int main() {
    static_assert(g());
}
Run Code Online (Sandbox Code Playgroud)

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;
      |                  ^ …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constexpr c++20 consteval

35
推荐指数
1
解决办法
1244
查看次数

什么是consteval?

显然,consteval它将成为C++ 20中的关键字.它的cppreference页面目前是空白的.它会是什么以及它与它有什么关系constexpr

c++ c++20 consteval

30
推荐指数
1
解决办法
2895
查看次数

为什么约束函数允许未定义的行为?

C ++中的常量表达式具有非常整洁的特性:它们的求值不能具有未定义的行为(7.7.4.7):

表达式e是核心常量表达式,除非按照抽象机([intro.execution])的规则对e求值,将求出以下值之一:

  • ...

  • 一种操作,其操作将具有本文档的[引言] [cpp]中指定的不确定的行为[注意:例如,包括带符号整数溢出([expr.prop]),某些指针算术([expr.add],除以零或某些移位操作-尾注];

尝试将13!in 的值存储在constexpr int确实产生一个不错的编译错误

constexpr int f(int n) 
{
    int r = n--;
    for (; n > 1; --n) r *= n;
    return r;
}

int main() 
{
    constexpr int x = f(13);
    return x;
}
Run Code Online (Sandbox Code Playgroud)

输出:

9:19: error: constexpr variable 'x' must be initialized by a constant expression
    constexpr int x = f(13);
                  ^   ~~~~~
4:26: note: value 3113510400 is outside the range of representable values …
Run Code Online (Sandbox Code Playgroud)

c++ undefined-behavior c++20 consteval

16
推荐指数
1
解决办法
308
查看次数

无法在 MSVC 上的初始值设定项列表内使用 consteval 函数

考虑最小化的代码片段:

#include <vector>

class Bar
{
public:
    constexpr Bar() {}
};

consteval Bar foo()
{
    return Bar();
}

int main()
{
    std::vector<Bar> bars{ foo(), foo() };
}
Run Code Online (Sandbox Code Playgroud)

这不能在最新的 MSVC 编译器(Visual Studio 2022 版本 17.3.3)上编译,但可以在 Clang 或 GCC 上编译。

编译器资源管理器

代码是否格式不正确,或者是 MSVC 中的错误?

c++ visual-c++ c++20 consteval

14
推荐指数
1
解决办法
655
查看次数

可以在 C++ 堆上创建具有 consteval 构造函数的类吗?

在下面的代码中,struct A有立即函数默认构造函数,并在动态内存中创建该结构的对象new A{}

struct A {       
    consteval A() {}
};

int main() {
    new A{};
}
Run Code Online (Sandbox Code Playgroud)

只有 Clang 接受。

海湾合作委员会抱怨

error: the value of '<anonymous>' is not usable in a constant expression
    6 |     new A{};
      |           ^
note: '<anonymous>' was not declared 'constexpr'
Run Code Online (Sandbox Code Playgroud)

MSVC 也这样做:

error C7595: 'A::A': call to immediate function is not a constant expression
Run Code Online (Sandbox Code Playgroud)

演示: https: //gcc.godbolt.org/z/6Px5WYGzd

这里是哪个编译器?

c++ new-operator language-lawyer consteval

11
推荐指数
1
解决办法
484
查看次数

可以从普通构造函数调用 consteval 委托构造函数吗?

在以下结构体定义中,构造函数A(int)将其工作委托给立即函数构造函数A()

struct A {       
    int i = 0;
    consteval A() = default;
    A(int) : A() {}
};
Run Code Online (Sandbox Code Playgroud)

Clang 接受了它,但 GCC 没有抱怨:

error: 'this' is not a constant expression
Run Code Online (Sandbox Code Playgroud)

和 MSVC:

'A::A': call to immediate function is not a constant expression
Run Code Online (Sandbox Code Playgroud)

演示: https: //gcc.godbolt.org/z/7e3fWzYzr

哪个编译器是正确的?

c++ language-lawyer consteval

10
推荐指数
1
解决办法
244
查看次数

非文字类型和常量表达式

struct A {       
    ~A() {}
    consteval A() {}
    consteval auto f() {}
};

int main() {
    A{};
    //A{}.f(); //1
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/4KPY5P7o7

该程序被 ICC、GCC 和 Clang 接受,但被 MSVC 拒绝,抱怨析构函数不在constexpr立即函数调用中。

添加标记行//1会导致所有四个编译器拒绝该代码。


问题:无论哪种情况,编译器都正确吗?如果正确,为什么?


请注意,这里有趣的部分是,A由于非constexpr平凡的析构函数,它是非字面的。删除其声明后,所有编译器都接受带有和不带有 的变体//1

constexpr对于/函数和常量表达式,有一些特定于非文字类型的限制consteval,但我认为它们中的任何一个都不应该适用于此。这些限制包括返回类型、参数类型、局部变量定义的类型、右值到左值的转换以及对象的修改。我想这里只有最后一个可以申请。但是[expr.const]/5.16中的修改到底意味着什么以及此处将修改哪个对象?

我还认为 MSVC 的抱怨是不正确的,因为对象的销毁不应该成为其构造函数立即调用的一部分。

另请参阅我之前启发这一问题的问题:constexpr 函数中的 Consteval 构造函数和成员函数调用

c++ language-lawyer c++20 consteval

10
推荐指数
1
解决办法
908
查看次数

从立即函数返回 std::vector

从 C++20 开始,std::vector可以在常量表达式中使用。据我所知,当前的 C++ 允许动态分配内存,条件是任何此类分配在常量表达式“结束”时都被释放。

但是,我遇到的情况是,在立即运行的情况下,规则可能会有所不同。请考虑以下示例:

consteval auto getVec() {
    return std::vector<int>(9);
}

static_assert( getVec().size() == 9 );
Run Code Online (Sandbox Code Playgroud)

这里立即consteval函数getVec返回 not-empty std::vector,其大小在常量表达式中验证。

我期望这段代码能够编译,因为所有释放都必须自动完成,并且实际上它在 Clang 中被接受libc++

但 MSVC 抱怨道:

error C7595: 'getVec': call to immediate function is not a constant expression
note: (sub-)object points to memory which was heap allocated during constant evaluation
fatal error C1903: unable to recover from previous error(s); stopping compilation
Run Code Online (Sandbox Code Playgroud)

GCC 的行为类似:

error: 'getVec()()' is not a constant expression …
Run Code Online (Sandbox Code Playgroud)

c++ stdvector language-lawyer c++20 consteval

10
推荐指数
1
解决办法
600
查看次数

约束允许在函数参数上使用static_assert吗?

当前,即使对它的所有调用确实为,也无法用于static_assert验证constexpr函数的参数constexpr。这是有道理的,因为在某些其他模块尝试调用该函数的情况下,编译器仍必须为此函数创建一个非constexpr实例。可悲的是,即使函数是static或位于匿名名称空间中,也是如此。

然而,C ++ 20将引入一个新的关键字consteval,类似于constexpr但不允许以非constexpr的方式调用函数。在这种情况下,编译器可以确定在编译时始终知道函数参数。因此,从理论上讲,应该有可能使用进行验证static_assert

问题是:标准允许吗?


例:

#include <iostream>

consteval char operator""_bchar(const char text[], const size_t length)
{
    static_assert(length == 8, "Binary char has to have 8 digits!"); // <-- This is currently not possible.
    uint8_t byte = 0;
    for (size_t i = 0; i != length; ++i)
    {
        byte <<= 1;
        byte |= text[i] == '1' ? 0b00000001 : 0b00000000;
    }
    return byte;
}

int main() …
Run Code Online (Sandbox Code Playgroud)

c++ static-assert c++20 consteval

9
推荐指数
1
解决办法
254
查看次数

clang 说对 void consteval 函数的调用不是常量表达式

clang(trunk) 给出以下代码的错误:

consteval void f() {}

int main() 
{ 
    f();  // error: call to consteval function 'f' is not a constant expression
          // note: subobject of type 'void' is not initialized
}
Run Code Online (Sandbox Code Playgroud)

而 gcc(trunk) 编译它没有错误。

我觉得这可能是一个 clang bug,因为 gcc 和 clang 都接受这个代码:

consteval int g() { return 42; }

int main() 
{ 
    g();  // ok
}
Run Code Online (Sandbox Code Playgroud)

这是要玩的代码。

那么这是一个 clang bug,还是代码格式不正确,或者有 ub,还是其他什么?


编辑:我觉得指出 clang 允许f从其他函数调用(如果它们也是保守的)可能是相关的。f它仅在从非 consteval 函数调用时给出错误:

consteval int h() 
{ 
    f();       // ok
    return 42; …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constant-expression c++20 consteval

9
推荐指数
1
解决办法
4606
查看次数