C ++ Singleton实例禁用重新调用

时间:2018-07-30 15:16:57

标签: c++ c++11 static singleton

使用Meyers单例时:

class Singleton
{
public:
    static Singleton& instance()
    {
        static Singleton instance;
        return instance;
    }

    void Hello()
    {
        std::cout <<"Hello!\n";
    }

protected:
    Singleton() = default;
    ~Singleton() {};

private:
    Singleton(Singleton const&);
    Singleton& operator=( Singleton const& );
};

您可以按以下方式调用实例:

Singleton::instance().Hello();

Singleton& s = Singleton::instance();
s.Hello();

但是我想知道是否有办法阻止这种情况:

Singleton::instance().instance();

如何避免将instance()作为方法(使用.来调用,而仅支持使用::的静态调用?

是否可以使用static_assert,模板enable_if或其他任何方式?

1 个答案:

答案 0 :(得分:7)

首先,我认为这不是实际问题。没有人会写Singleton::instance().instance().instance().Hello()。或者更确切地说,如果人们故意写这些东西,我认为您有更大的问题。可以,没关系。


如果您真的想避免这种情况,那么只需将instance()移动到类之外,这样它就不再是成员函数。您没有什么要断言或约束的,因为您无法确定是否在某个对象上调用了静态成员函数(并且不能用带有相同参数列表的非静态成员函数重载静态成员函数)。您既可以写Singleton::instance()也可以写Singleton::instance().instance(),或者都不写。

最简单的就是:

class Singleton {
    // ... 
    friend Singleton& make_singleton();
};

Singleton& make_singleton() {
    static Singleton instance;
    return instance;
}

现在它只是make_singleton().Hello(),根本没有其他方法可以写出来。可以通过将其包装在单例类模板工厂中来任意泛化:

template <typename T>
struct SingletonFactory
    static T& instance() {
        static T instance;
        return instance;
    }
};

SingletonFactory<Singleton>::instance().Hello(); // ok
SingletonFactory<Singleton>::instance().instance().Hello(); // error