gpt4 book ai didi

c++ - 带有 C++ 模板的构建器模式

转载 作者:可可西里 更新时间:2023-11-01 18:18:22 28 4
gpt4 key购买 nike

我有一个高度可配置的类,其中包含许多模板参数,如下所示:

template<bool OptionA = false, bool OptionB = false, bool OptionC = false, class T = Class1B>
class MyClass
{
}

现在,如果我想创建类类型并且我只想将 OptionB 设置为 true,我必须执行以下操作:

MyClass<false, true>

特别是对于许多模板参数,这会变得很麻烦。

不,我的问题是,是否有任何示例可用于使用构建器模式创建基于模板的类类型?

我正在寻找这样的东西:

class Builder
{
useOptionA();
useOptionB();
useOptionC();
useClass2B(); //instead of Class1B
create();
}

最后调用 Builder.useOptionB().useOptionC().useClass2B.create()应该返回 MyClass<false, true, true, Class2B> .这可能吗?

编辑:将类添加到模板参数列表。

最佳答案

正如其他人所说,最简单的方法是使用 enum 而不是 Builder。但是,如果您确实想要一个 Builder,您可以尝试这样的事情:

template<bool OptionA = false,
bool OptionB = false,
bool OptionC = false,
typename T = Class1B>
struct Builder_t
{
Builder_t() = default;
// ~Builder_t() { std::cout << "Builder dtor." << std::endl; }

auto useOptionA() -> Builder_t<true, OptionB, OptionC, T> { return {}; }
auto useOptionB() -> Builder_t<OptionA, true, OptionC, T> { return {}; }
auto useOptionC() -> Builder_t<OptionA, OptionB, true, T> { return {}; }
auto useClass2B() -> Builder_t<OptionA, OptionB, OptionC, Class2B> { return {}; }

MyClass<OptionA, OptionB, OptionC, T> create() { return {}; }
};
using Builder = Builder_t<>;

// ...

// Build MyClass<true, false, false, Class2B>:
auto ma2 = Builder{}.useOptionA().useClass2B().create();

这会导致每个函数返回一个不同的Builder,其模板将被下一个函数使用;最终模板用作 MyClass 的模板。每个函数都会修改其指定的模板参数,从而允许生成器模式的编译时版本。不过,它确实有成本,如果取消注释用户定义的析构函数,这一点就会变得很明显。


考虑这个简单的测试程序:

#include <iostream>
#include <typeinfo>

class Class1B {};
class Class2B {};

template<bool OptionA = false,
bool OptionB = false,
bool OptionC = false,
typename T = Class1B>
class MyClass
{
public:
MyClass() {
std::cout << "MyClass<"
<< OptionA << ", "
<< OptionB << ", "
<< OptionC << ", "
<< "type " << typeid(T).name() << ">"
<< std::endl;
}
};

template<bool OptionA = false,
bool OptionB = false,
bool OptionC = false,
typename T = Class1B>
struct Builder_t
{
Builder_t() = default;
// ~Builder_t() { std::cout << "Builder dtor." << std::endl; }

auto useOptionA() -> Builder_t<true, OptionB, OptionC, T> { return {}; }
auto useOptionB() -> Builder_t<OptionA, true, OptionC, T> { return {}; }
auto useOptionC() -> Builder_t<OptionA, OptionB, true, T> { return {}; }
auto useClass2B() -> Builder_t<OptionA, OptionB, OptionC, Class2B> { return {}; }

MyClass<OptionA, OptionB, OptionC, T> create() { return {}; }
};
using Builder = Builder_t<>;

int main()
{
std::cout << std::boolalpha;

std::cout << "Default:\n";
std::cout << "Direct: ";
MyClass<> m;
std::cout << "Builder: ";
auto mdefault = Builder{}.create();
std::cout << std::endl;

std::cout << "Builder pattern:\n";
std::cout << "A: ";
auto ma = Builder{}.useOptionA().create();
std::cout << "C: ";
auto mc = Builder{}.useOptionC().create();
std::cout << "---\n";

std::cout << "AB: ";
auto mab = Builder{}.useOptionA().useOptionB().create();
std::cout << "B2: ";
auto mb2 = Builder{}.useOptionB().useClass2B().create();
std::cout << "---\n";

std::cout << "ABC: ";
auto mabc = Builder{}.useOptionA().useOptionB().useOptionC().create();
std::cout << "AC2: ";
auto mac2 = Builder{}.useOptionA().useOptionC().useClass2B().create();
std::cout << "---\n";

std::cout << "ABC2: ";
auto mabc2 = Builder{}.useOptionA().useOptionB().useOptionC().useClass2B().create();
}

正常情况下,输出如下(使用GCC):

Default:
Direct: MyClass<false, false, false, type 7Class1B>
Builder: MyClass<false, false, false, type 7Class1B>

Builder pattern:
A: MyClass<true, false, false, type 7Class1B>
C: MyClass<false, false, true, type 7Class1B>
---
AB: MyClass<true, true, false, type 7Class1B>
B2: MyClass<false, true, false, type 7Class2B>
---
ABC: MyClass<true, true, true, type 7Class1B>
AC2: MyClass<true, false, true, type 7Class2B>
---
ABC2: MyClass<true, true, true, type 7Class2B>

但是,如果我们取消注释析构函数...

Default:
Direct: MyClass<false, false, false, type 7Class1B>
Builder: MyClass<false, false, false, type 7Class1B>
Builder dtor.

Builder pattern:
A: MyClass<true, false, false, type 7Class1B>
Builder dtor.
Builder dtor.
C: MyClass<false, false, true, type 7Class1B>
Builder dtor.
Builder dtor.
---
AB: MyClass<true, true, false, type 7Class1B>
Builder dtor.
Builder dtor.
Builder dtor.
B2: MyClass<false, true, false, type 7Class2B>
Builder dtor.
Builder dtor.
Builder dtor.
---
ABC: MyClass<true, true, true, type 7Class1B>
Builder dtor.
Builder dtor.
Builder dtor.
Builder dtor.
AC2: MyClass<true, false, true, type 7Class2B>
Builder dtor.
Builder dtor.
Builder dtor.
Builder dtor.
---
ABC2: MyClass<true, true, true, type 7Class2B>
Builder dtor.
Builder dtor.
Builder dtor.
Builder dtor.
Builder dtor.

Builder_t::create() 之前的每次调用都会创建一个不同的 Builder_t,所有这些都会在实例创建后销毁。这可以通过将 Builder_t 设为 constexpr 类来缓解,但如果有大量参数需要处理,这可能会减慢编译速度:

template<bool OptionA = false,
bool OptionB = false,
bool OptionC = false,
typename T = Class1B>
struct Builder_t
{
// Uncomment if you want to guarantee that your compiler treats Builder_t as constexpr.
// size_t CompTimeTest;

constexpr Builder_t()
// Uncomment if you want to guarantee that your compiler treats Builder_t as constexpr.
// : CompTimeTest((OptionA ? 1 : 0) +
// (OptionB ? 2 : 0) +
// (OptionC ? 4 : 0) +
// (std::is_same<T, Class2B>{} ? 8 : 0))
{}

constexpr auto useOptionA() -> Builder_t<true, OptionB, OptionC, T> { return {}; }
constexpr auto useOptionB() -> Builder_t<OptionA, true, OptionC, T> { return {}; }
constexpr auto useOptionC() -> Builder_t<OptionA, OptionB, true, T> { return {}; }
constexpr auto useClass2B() -> Builder_t<OptionA, OptionB, OptionC, Class2B> { return {}; }

constexpr MyClass<OptionA, OptionB, OptionC, T> create() { return {}; }
};
using Builder = Builder_t<>;

// ....

// Uncomment if you want to guarantee that your compiler treats Builder_t as constexpr.
// char arr[Builder{}/*.useOptionA()/*.useOptionB()/*.useOptionC()/*.useClass2B()/**/.CompTimeTest];
// std::cout << sizeof(arr) << '\n';

关于c++ - 带有 C++ 模板的构建器模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40071779/

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