在 C++20 中模拟 std::start_lifetime_as_array

问题描述 投票:0回答:1

根据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
,则相当于
std::start_lifetime_as<U>(p)
,其中 U 是“n Ts 的数组”类型。

但是

n
仅在运行时才知道。

c++ memory-management c++20 undefined-behavior lifetime
1个回答
0
投票

类似这样的:

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
    开始。

© www.soinside.com 2019 - 2024. All rights reserved.