【发布时间】:2017-01-18 06:39:30
【问题描述】:
我们正在弃用我们项目中的 ACE 库,该库由大约 120 个二进制文件组成,并且在许多二进制文件中我们使用了 ACE_Singleton。因为在弃用后我们将不再有这个类,所以我们正在考虑编写自己的通用单例在所有这些二进制文件中通用的共享库中,我们想要实现的目标之一是如果有人从这个类继承(使用 CRTP)说 Logger,即使 Logger 构造函数是公共的,那么我们也不能创建两个 logger 对象。 为了说明,让我们假设我的单例类名称是 GenericSingleton,我的客户端类是记录器,那么下面的代码应该会抛出错误:
class Logger:public GenericSingleton<Logger>
{
public:
Logger()
{
}
};
int main()
{
Logger obj;// first instance no issue
Logger obj1; // second instance is problem as it is inherited from singleton
}
那么有人可以建议我应该如何设计 GenericSingleton 以便在创建第二个对象时我应该得到编译时错误?
简而言之,如果我的派生类没有私有构造函数、析构函数复制构造函数等,那么可以在编译时使用 static_assert 进行检查?
【问题讨论】:
-
您也许可以使用例如
std::once_flag允许构造函数只被调用一次。但最常见的方法是根本没有公共构造函数,将其设为私有,并有一个公共static“getter”函数来获取该类的唯一实例。 -
你说得对,单例类构造函数应该是私有的,但是在设计库函数时,我们不应该假设库用户会编写正确的客户端类,所以我想在库级别处理,如果某些类继承自 GenericSingleton 并且如果没有私有构造函数,那么应该会发生编译时错误
-
@Kapil 希望提供健壮且防错的库代码固然不错,但在某种程度上,您必须相信客户会为自己编写正确的代码。此外,还有许多错误(至少在 C++ 中)只是无法在编译时被捕获。
-
@Kyle 我认为完整的数据类型(例如 Logger)已传递给 GenericSingleton 模板类,所以我们不能检查该类型并确定它是否具有私有构造函数
-
@Kapil 如果您同意对子(单例)类实施实施某些限制,那么我想您会喜欢我添加到答案中的方法。