根据cppreference,目前没有编译器支持
std::start_lifetime_as_array
。
但是,SO 答案 表明它可以在 C++20 中“模拟”,如下所示:
template<class T>
requires (std::is_trivially_copyable_v<T> && std::is_implicit_lifetime_v<T>)
T* start_lifetime_as(void* p) noexcept
{
return std::launder(static_cast<T*>(std::memmove(p, p, sizeof(T))));
}
我们如何才能类似地模拟
std::start_lifetime_as_array
而不调用未定义的行为?
cppreference 说的是
template< class T >
T* start_lifetime_as_array( void* p, std::size_t n ) noexcept;
隐式创建一个元素类型为 T 且长度为
的数组。准确地说,如果n
是n > 0
,则相当于true
,其中 U 是“n Ts 的数组”类型。std::start_lifetime_as<U>(p)
但是
n
仅在运行时才知道。
类似这样的:
template<class T>
requires (std::is_trivially_copyable_v<T> && std::is_implicit_lifetime_v<T>)
T* start_lifetime_as_array(void* p, std::size_t n) noexcept
{
if(n == 0)
return p;
else
return std::launder(static_cast<T*>(std::memmove(p, p, sizeof(T)*n)));
}
但是,您显示的
std::start_lifetime_as
和上面提供的功能都完全不符合标准中的规范。例如:
指针上的
const
/volatile
限定的所有组合都缺少重载。
如果
T
不完整,则调用应该是格式错误的。这尚未经过测试,并且必须以不以其他方式评估 requires
子句的方式进行测试,因为如果 T
不完整,类型特征会导致未定义的行为。
std::is_implicit_lifetime_v<T>
是C++23,不是C++20,在C++20中没办法实现
std::is_trivially_copyable_v<T>
实际上并不是必需的。但是,如果未满足,则某些子对象在调用后可能具有未指定或不确定的值。如果嵌套对象不是隐式生命周期类型,那么它们的生命周期不会以 std::start_lifetime_as
开始。