如何使用折叠表达式实现Builder类的多类型链式addFoo成员函数调用
如何使用折叠表达式实现Builder类的多类型链式addFoo成员函数调用
没问题,这个需求完全可以用C++17的折叠表达式实现!其实链式成员函数调用正是折叠表达式擅长的场景之一,关键是要掌握正确的折叠语法来串联每个addFoo调用。
首先,先明确你的核心需求:给一个FooTypes模板参数包,我们要把Builder(data).addFoo<Foo1>(createUuid()).addFoo<Foo2>(createUuid())...这种链式调用用折叠表达式自动展开。
直接可行的实现方案
你只需要调整bar函数的实现,用右折叠表达式来串联每个addFoo调用:
#include <concepts> // 假设你已经定义了Builder、SomeData、createUuid这些实体 template <std::constructible_from<std::string>... FooTypes> void bar(SomeData data) { // 核心:用折叠表达式自动链式调用每个addFoo auto builder = (Builder(data).addFoo<FooTypes>(createUuid()) ...); // 这里继续处理你的builder逻辑 // do something fancy with that builder }
为什么这个写法有效?
当你传入FooTypes = Bar, Baz时,折叠表达式会自动展开成:
auto builder = Builder(data).addFoo<Bar>(createUuid()).addFoo<Baz>(createUuid());
- 折叠表达式的
...会遍历参数包中的每个FooType,依次在之前的Builder对象(右值,因为addFoo返回Builder&&)上调用addFoo<FooType>(createUuid()) - 你的
addFoo是右值引用限定的(Builder&& addFoo(...) &&),而每次调用addFoo返回的都是右值引用,刚好符合后续调用的要求,不会有左/右值不匹配的问题 - 如果参数包为空(即没有传入任何
FooType),表达式会直接退化为Builder(data),逻辑依然合理
额外的小提示
如果你担心空参数包的场景(比如希望必须至少传入一个FooType),可以添加一个编译期检查:
#include <type_traits> template <std::constructible_from<std::string>... FooTypes> void bar(SomeData data) { static_assert(sizeof...(FooTypes) > 0, "至少需要传入一个FooType"); auto builder = (Builder(data).addFoo<FooTypes>(createUuid()) ...); // 后续操作 }
这样就能确保调用bar时必须提供至少一个类型参数,避免无意义的空Builder创建。
备注:内容来源于stack exchange,提问作者PluginPenguin
相关产品推荐
相关产品推荐

