作者:臭小子 | 来源:互联网 | 2023-06-08 15:19
假设我们有一些课程struct Foo { constexpr Foo(int& x) : x_(x) { x_++; } constexpr ~Foo() noexcept {
假设我们有一些课程
struct Foo {
constexpr Foo(int& x) : x_(x) { x_++; }
constexpr ~Foo() noexcept { x_++; }
int& x_;
};
在 C++20 中,g++-10 -std=c++20
我们可以有这样的函数:
constexpr int do_foo_1() {
int x = 0;
Foo* p = new Foo(x);
delete p;
return x;
}
int main() {
static_assert(do_foo_1() == 2);
}
让我们尝试将运算符new
分为内存分配和就地构造。所以新函数看起来像这样:
constexpr int do_foo_2() {
int x = 0;
Foo* p = static_cast(::operator new(sizeof(Foo)));
p = ::new ((void*) p) Foo(x);
p->~Foo();
::operator delete(p);
return x;
}
但是现在有两个错误:我们的内存分配new和placement new不是constexpr!
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t)’
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t, void*)’
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t)’
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t, void*)’
因此,让我们尝试解决这些错误。随着
我们能有这样的代码:
题
我的用法和标准库中这些运算符的用法有什么区别?引擎盖内std::construct_at
和std::allocator::allocate
引擎盖下不是发生同样的事情吗?
笔记
我试图通过简单地复制它的实现来复制 std::construct_at
但我得到了同样的错误:
error: ‘constexpr decltype (...) my_construct_at(_Tp*, _Args&& ...) [...]’ called in a constant expression
error: call to non-‘constexpr’ function ‘void* operator new(std::size_t, void*)
回答
我的用法和标准库中这些运算符的用法有什么区别?
您的用法未调用std::allocator::allocate
或std::construct_at
。
这些特定功能 - 以及其他一些功能 - 被特别授予正常规则的例外情况:
为了确定表达式E是否是核心常量表达式,对std?::?allocator
[allocator.members] 中定义的成员函数的调用的评估
,其中T
是文字类型,不会取消E作为核心常量表达式的资格,即使对此类调用的实际评估将无法满足核心常量表达式的要求。类似地,为一个呼叫的评价std?::?destroy_at
,
std?::?ranges?::?destroy_at
,std?::?construct_at
,或std ::范围:: construct_at不资格????Ë从一个核心常量表达式除非:[...]
至于普通new
表达式,在不断评估期间,它从不调用::operator new
:
在常量表达式的求值过程中,总是省略对分配函数的调用。