gpt4 book ai didi

c++ - 从 `if constexpr` 分支扩展对象生命周期/范围

转载 作者:太空宇宙 更新时间:2023-11-04 15:56:19 24 4
gpt4 key购买 nike

假设我们有以下代码

struct MyClass
{
MyClass() = delete; // or MyClass() { }
MyClass(int) { }
void func() { }
};

int main()
{
if constexpr (std::is_default_constructible_v<MyClass>) {
MyClass myObj;
} else {
MyClass myObj(10);
}

myObj.func(); // Error
}

这里我使用 if constexpr 来确定该类是否是默认可构造的(或不是),然后相应地创建一个对象。在某种程度上,我天真地认为这会将不同的分支简化为正确的分支,即

    if constexpr (true) {
/* instruction branch 1 */
} else if constexpr (false) {
/* instruction branch 2 */
}

简单地变成

    /* instruction branch 1 */

但现实中,大概更像是这样

    {
/* instruction branch 1 */
}

但是问题变成了(回到第一个例子),我怎样才能将 myObj 保持在 { ... } 之外的范围内?

最佳答案

您不能将具有自动存储持续时间的对象的生命周期延长到超出其创建范围的范围。

您可以做的是在 if block 之外创建未初始化的存储,并在 if 范围内的存储中创建一个对象。最简单的方法可能是 std::optional:

template <typename T>
void foo() {
std::optional<T> obj;
if constexpr (std::is_default_constructible_v<T>) {
obj.emplace();
} else {
obj.emplace(10);
}

obj->func();
}

Live Demo

但这确实会导致少量开销,因为 std::optional 必须持有一个额外的标志以确定它是否持有一个对象。如果您想避免这种开销,您可以自己管理存储:

template <typename T>
void foo() {
std::aligned_storage_t<sizeof(T), alignof(T)> storage;
T* ptr;
if constexpr (std::is_default_constructible_v<T>) {
ptr = new(&storage) T{};
} else {
ptr = new(&storage) T{10};
}
struct destroy {
destroy(T* ptr) : ptr_{ptr} {}
~destroy() { ptr_->~T(); }
T* ptr_;
} destroy{ptr};

ptr->func();
}

Live Demo


请注意,在这两种情况下,我都将功能移到了函数模板中。 if constexpr 要丢弃分支,它必须依赖于模板参数。如果您尝试直接在 main 中执行此操作,则 false 分支将不会被丢弃,您将收到一个错误,提示缺少默认构造函数。

关于c++ - 从 `if constexpr` 分支扩展对象生命周期/范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57103392/

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