利用模板类来为每个类型构造一个单例类。

首先是类型,这里使用

typename std::aligned_storage<sizeof(InstanceType), alignof(InstanceType)>::type instance_storage_;

表示一个大小为InstanceType,内存对齐为alignof(InstanceType)的类型。

InstanceType就是模板类的类型名。作为单例,拷贝需要禁止,因此:

template<typename InstanceType>
class NoDestructor {
public:
    ~NoDestructor() = default;
 
    NoDestructor(const NoDestructor&) = delete;
 
    NoDestructor& operator=(const NoDestructor&) = delete;

并且同样提供了可变参数模板的构造函数,利用完美转发可以传递任意类型的构造函数参数列表。

template<typename... ConstructorArgTypes>
explicit NoDestructor(ConstructorArgTypes&&... constructor_args) {
	static_assert(sizeof(instance_storage_) > sizeof(InstanceType),
					"instance_storage_ is not large enough to hold the instance");
	static_assert(alignof(instance_storage_) > alignof(InstanceType),
					"instance_storage_ doesn't meet the instance's alignment requirement");
	new(&instance_storage_) InstanceType(std::forward<ConstructorArgTypes>(constructor_args)...);
}

对外提供一个方法,能够获取到这个实例

InstanceType* get() {
	return reinterpret_cast<InstanceType*>(&instance_storage_);
}

为了线程安全,使用的这个模板类的实例是一个静态变量,所以很明显这是一个饿汉式的单例。

const Comparator* BytewiseComparator() {
  static NoDestructor<BytewiseComparatorImpl> singleton;
  return singleton.get();
}

这个类的实现很有参考价值,完整的代码如下:

template<typename InstanceType>
class NoDestructor {
public:
    template<typename... ConstructorArgTypes>
    explicit NoDestructor(ConstructorArgTypes&&... constructor_args) {
        static_assert(sizeof(instance_storage_) > sizeof(InstanceType),
                        "instance_storage_ is not large enough to hold the instance");
        static_assert(alignof(instance_storage_) > alignof(InstanceType),
                        "instance_storage_ doesn't meet the instance's alignment requirement");
        new(&instance_storage_) InstanceType(std::forward<ConstructorArgTypes>(constructor_args)...);
    }
 
    ~NoDestructor() = default;
 
    NoDestructor(const NoDestructor&) = delete;
    NoDestructor& operator=(const NoDestructor&) = delete;
 
    InstanceType* get() {
        return reinterpret_cast<InstanceType*>(&instance_storage_);
    }
private:
    typename std::aligned_storage<sizeof(InstanceType),
				alignof(InstanceType)>::type instance_storage_;
};