我正在尝试创建一个遵循构建器模式并且在编译时完全运行的类(使用新的consteval
C++20 中的关键字),但无论我尝试什么都不起作用。例如,这是行不通的:
#include <vector>
class MyClass
{
private:
std::vector<int> data;
public:
consteval MyClass& setData()
{
this->data = {20};
return *this;
}
consteval std::vector<int> build()
{
return data;
}
};
int main()
{
std::vector<int> data = MyClass().setData().build();
}
这给出了错误“<anonymous>
不是常量表达式”。这让我相信我应该返回类的副本:
#include <vector>
class MyClass
{
private:
std::vector<int> data;
public:
consteval MyClass setData()
{
// https://herbsutter.com/2013/04/05/complex-initialization-for-a-const-variable/
return [&]{
MyClass newClass;
newClass.data = {20};
return newClass;
}();
}
consteval std::vector<int> build()
{
return data;
}
};
int main()
{
std::vector<int> data = MyClass().setData().build();
}
然而,我遇到了同样的错误。我应该如何在 C++ 中使用常量时间构建器模式?看来这只发生在vector
s,我使用的是支持C++20的版本constexpr vector
s.
您的代码无法编译,因为当前的 C++ 只允许在常量表达式中进行“瞬态”分配。这意味着在常量表达式求值期间,允许动态分配内存 (C++20 起),但前提是任何此类分配在常量表达式“结束”时都已释放。
在您的代码中,表达式MyClass().setData()
必须是常量表达式,因为它是立即调用(这意味着调用consteval
函数,而不是发生在另一个函数内部的函数consteval
函数或内部if consteval
堵塞)。表达方式MyClass().setData().build()
也必须是常量表达式。这意味着,虽然MyClass().setData().build()
正在评估中,允许动态分配,但在评估结束时不得有“幸存”分配MyClass().setData()
也不在结束时MyClass().setData().build()
.
既然没有办法阻止这样的结果MyClass().setData()
由于具有实时分配,您只能在封闭的内部调用它consteval
函数或if consteval
堵塞。例如,以下内容将是有效的:
consteval int foo() {
return MyClass().setData().build()[0];
}
请注意,临时MyClass
对象(因此std::vector<int>
子对象)将被销毁,因此所有动态分配都将在之前被清理foo()
返回。
你想将向量保留在最外层之后consteval
功能完成?抱歉,您不能这样做——至少在当前版本的 C++ 中不能。您需要将其内容复制到std::array
或其他一些不使用动态分配的对象。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)