gpt4 book ai didi

c++ - 正确使用 std::launder

转载 作者:行者123 更新时间:2023-12-01 14:07:03 24 4
gpt4 key购买 nike

我想确认我是否正确使用 std::launder(...)确保我正确理解它的用法。
我正在创建一个 Result<U,E>在基于 Rust 实现的 C++ 中。

template <typename E>
class ResultStorage<void, E, std::enable_if_t<std::is_trivially_destructible_v<E>>> {
using type = typename std::aligned_storage<sizeof(E), alignof(E)>::type;

public:
explicit constexpr ResultStorage(const Ok<void>&) noexcept : tag_(ResultTag::OK) {}

explicit constexpr ResultStorage(const Ok<void>&&) noexcept : tag_(ResultTag::OK) {}

explicit constexpr ResultStorage(const Err<E>& err) noexcept(std::is_nothrow_copy_constructible<E>())
: tag_(ResultTag::ERR) {
new (&error_) E(err.get_error());
}
explicit constexpr ResultStorage(const Err<E>&& err) noexcept(std::is_nothrow_move_constructible<E>())
: tag_(ResultTag::ERR) {
new (&error_) E(std::move(err.get_error()));
}

~ResultStorage() = default;

[[nodiscard]] constexpr E& get_error() & noexcept {
assert_err(tag_);
return *std::launder(reinterpret_cast<E*>(&error_));
}

// Code omitted for brevity
private:
ResultTag tag_;
type error_;

template <typename Rv, typename Ev>
friend class result::Result;
};
在我使用的代码中 using type = typename std::aligned_storage<sizeof(E), alignof(E)>::type;作为我的存储类型。我相信我需要使用 std::launder(...)当我像这样从函数返回错误类型时:
    [[nodiscard]] constexpr E& get_error() & noexcept {
assert_err(tag_);
return *std::launder(reinterpret_cast<E*>(&error_));
}
我相信我需要使用 std::launder(...) 的原因是因为传入的错误类型可能是一个结构体,可能带有 const值那么看来,如果我不使用 std::launder(...)然后在第一次初始化时,它将引用 const成员值,如果我要重用这个分配的存储,它总是指初始 const成员(member)值(value)。
我对 std::launder有一个初步的了解因此,对什么情况需要使用它的解释将不胜感激。我已经查看了这个函数的 cppreference,但仍然觉得它很神秘。
注意:完整的实现可以在 github 上找到.

最佳答案

我不会冒险去猜测 std::launder ,但您的代码有另一个问题,解决它会使 std::launder不再需要:

new (&error_) E(err.get_error());
(reinterpret_cast<E*>(&error_);
这是错误的,因为标准保证创建的对象实际上从 &error 开始。仅适用于标准布局类型。我知道这在实践中实际上并非如此的一种特殊情况是当您有多重继承时。
所以正确的做法是:
// class data member:
E* ptr = nullptr;

// then:
ptr = new (&error_) E(err.get_error());
并且只能使用 ptr访问存储的对象。这也会使 std::launder不再需要了。
正如您所看到的,当您使用 C++ 进行如此低级的学习时,存在许多微妙的陷阱。

关于c++ - 正确使用 std::launder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63002437/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com