是否允许调用方对我的 Builder 类使用任何指针类型(包括智能指针)?

Allow the caller to use any pointer type (including smart pointers) with my Builder class?

本文关键字:指针 任何 类型 智能 包括 我的 许调用 调用 是否 Builder      更新时间:2023-10-16

实现Builder forFoo的标准方法是这样的:

class Foo::Builder {
public:
Builder& setBar(bool bar);
...
Foo build() const;
};

仅当调用方尝试将此类与智能指针一起使用时:

auto builder = std::make_shared<Foo::Builder>()->setProperty(...);

生成器不能以这种方式使用,因为setProperty()将返回对对象的引用,该对象将在此语句完成执行时被销毁。当调用方在同一语句中调用build()并且Builder类永远不会绑定到变量名时,这无关紧要。

但是,在我的应用程序中,我希望能够在派生的构建器对象上进行一些配置,然后将其传递给另一个类的构造函数(该构造函数将其作为指向基类型的指针接收(。我还希望调用者能够决定所用指针的类型。我可以通过Foo::Builder模板来做到这一点吗?有没有更好的设计模式更适合这一点?我对想法持开放态度。

控制其他人用来指向实例的内容不是类业务。如果另一个类在其构造函数中接收到指向Builder的指针,则可以使构造函数成为模板:

struct OtherClass {
template <typename T>
OtherClass(T t) {
t->setProperty();
}
};

如果要将T限制为具有返回Builderoperator->的类型,则可以等待C++20概念,也可以编写允许SFINAE的类型特征:

template <typename P,typename T>
struct points_to : std::false_type {};
template <typename T>
struct points_to<T*,T> : std::true_type {};
template <typename P>
struct points_to<P,std::decay_t<decltype(std::declval<P>().operator->())>> : std::true_type {};

然后,构造函数可以通过以下方式要求points_to<T,Builder>

struct AnotherClass {
template <typename T,typename = std::enable_if_t<points_to<T,Builder>::value,void>>
AnotherClass(T t){}
};

但是,错误消息不会比上面的非受限模板好多少。static_assert有助于获取可读的错误消息:

struct AnotherClass {
template <typename B>
AnotherClass(B b){
static_assert(points_to<B,Builder>::value,"b is not pointing to a Builder");
}
};

现场示例