没有unique_ptr的现代C ++构建器模式

灰猫

我想在现代C ++中实现一个生成器模式。来自Java背景,这是我想模仿的东西:

// Usage
FooBuilder builder;
builder.setArg1(a);
builder.setArg2(b);
Foo foo = builder.build();

// Implementation
public class FooBuilder {
    // ...
    public Foo build() {
        return new Foo(a, b);
    }
}

典型的较旧的教科书只是建议人们这样做,就像在C ++中那样:

class FooBuilder {
    // ...
    Foo* build() {
        return new Foo(m_a, m_b);
    }
}

这显然不是一个好主意,因为处理原始指针可能容易出错。到目前为止,我想到的最好的方法是std::unique_ptr手动使用

class FooBuilder {
    // ...
    std::unique_ptr<Foo> build() {
        return std::make_unique<Foo>(m_a, m_b);
    }
}

// Usage
auto fooPtr = builder.build();
Foo& foo = *fooPtr;
foo.someMethod();

更好,因为它不需要手动delete,这种两层转换为引用是很丑陋的,而且更重要的是,它使用堆分配,而简单的无生成器版本只需要简单的堆栈分配就可以了:

Foo foo(..., ...); // <= on stack

有没有更好的方法可以做到这一点,即没有unique_ptr或为Foo提供某种堆栈上的分配?

保罗·贝朗格

通常,如果Foo是copy_constructible,则可以按值返回Foo。

#include <type_traits>

class Foo
{
    int i;

public:
    Foo(int i): i(i){}

};

static_assert(std::is_copy_constructible<Foo>::value, "Foo is copy-constructible");

struct FooFactory
{
    //...
    Foo build() {return Foo(1);}
};


int main()
{
    FooFactory factory;
    //...
    Foo foo = factory.build();
}

c ++ 17中的新增功能保证了copy elision,这意味着即使类型没有复制或移动构造函数,您也可以按值返回:

#include <type_traits>

class Foo
{
    int i;

public:
    Foo(int i): i(i){}
    // regular copy constructors don't exist for whatever reason. 
    Foo() = delete;
    Foo(Foo const& ) =delete;
    Foo(Foo&& ) = delete;
    Foo& operator=(Foo const&) = delete;
    Foo& operator=(Foo&& ) = delete;
};

static_assert(not std::is_copy_constructible<Foo>::value, "Foo is definitely not copy-constructible");


struct FooFactory
{
    //...
    Foo build() {return Foo(1);}
};


int main()
{
    FooFactory factory;
    //...
    Foo foo = factory.build();
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C#构建器模式

具有C ++模板的构建器模式

带有 unique_ptr 的工厂模式

了解C#中的构建器模式

C++中的链式构建器模式

如果需要存储删除器,unique_ptr如何没有开销?

使用带有构建器模式的List <T>-C#

如何在一个构建器类中具有多个构建器模式?

有效Java中的构建器模式

使用私有变量的Javascript构建器模式

具有非平凡子类树的Java构建器模式

构建器模式-带有前提条件的方法

只有一个类的构建器模式

带有 lambda 删除器的 Unique_ptr

unique_ptr 的有状态自定义删除器

具有std :: unique_ptr的容器的访问器函数

现代编译器在使用构建器模式时是否使用复制省略

使用没有内部静态类的流畅的构建器模式进行工作流

将具有自定义删除器的unique_ptr移到shared_ptr

包装器使用普通函数删除器构建std :: unique_ptr

转移IDisposable对象的所有权和构建器设计模式

扩展方法、构建器模式和流畅接口之间有什么区别?

有谁知道使用构建器模式包装JOptionPane的代码?

如何使用具有相同属性的构建器模式和继承

具有构建器模式的“动态”关键字隐藏了扩展方法

带有在编译时评估的向量的构建器模式(使用 `consteval`)

构建器模式是否适合于相同的表示形式/输出,但过程稍有不同?

具有映射类型和const断言的TypeScript构建器模式

防止对象在流畅的构建器模式C#中实例化