meg*_*ayu 3 c++ design-patterns builder c++20
我试图创建一个遵循构建器模式并且在编译时完全运行的类(使用constevalC++20 中的 new 关键字),但无论我尝试什么都不起作用。例如,这是行不通的:
#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();
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误“<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();
}
Run Code Online (Sandbox Code Playgroud)
然而,我遇到了同样的错误。我应该如何在 C++ 中使用常量时间构建器模式?看来这只发生在vectors 上,而我使用的是支持 C++20 s 的版本constexpr vector。
您的代码无法编译,因为当前的 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];
}
Run Code Online (Sandbox Code Playgroud)
请注意,临时MyClass对象(以及std::vector<int>子对象)将被销毁,因此所有动态分配都将在返回之前被清理foo()。
您想在最外面的函数完成后保留向量consteval吗?抱歉,您不能这样做——至少在当前版本的 C++ 中不能。您需要将其内容复制到std::array不使用动态分配的对象或其他类型的对象中。