0
\$\begingroup\$

Is this a correct implementation of a generic Meyers Singleton in C++17? Any tips appreciated.

Singleton.h

#ifndef SINGLETON_H
#define SINGLETON_H

template<class T>
class Singleton
{
public:
    
    static T& get()
    {
        static T obj;
        return obj;
    }

protected:

    Singleton() = default;
    virtual ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton(Singleton&&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    Singleton& operator=(Singleton&&) = delete;

};

#endif

MySingleton.h

#ifndef MYSINGLETON_H
#define MYSINGLETON_H

class MySingleton : public Singleton<MySingleton>
{
    friend class Singleton<MySingleton>;

public:

    // public members

private:
    
    MySingleton() {};
    ~MySingleton() {};

};

#endif
\$\endgroup\$
2
  • \$\begingroup\$ You will find issues with using templated singletons and shared libraries. You may have a single instance per shared library the compiler is under no obligation to remove duplicates across shared libraries (as the language does not even consider this). \$\endgroup\$ – Martin York Jan 25 at 22:55
  • \$\begingroup\$ Sinelton is best used in conjunction with a builder pattern. Otherwise, you will have issues with testing. You should be able to install a different Singleton object depending on the context of where you using it (Still keeping the same concept of having one object for the lifetime of the application it just may be different in different contexts). \$\endgroup\$ – Martin York Jan 25 at 22:58
2
\$\begingroup\$

Overview

I am not sure this byes you anything in savings.
Its one static function and making sure that you can't copy/move the object.

There are some issues aound using templates to implement this as I have tried exactly the same before. If this is a single application it is find but if you start using shared libraries then you may run into issues where you have several instances of T because there is a unique version of get() in every shared library that has not been removed.

Code Review

Not unique.

#ifndef SINGLETON_H
#define SINGLETON_H

Put your code in a namespace and add the namespace the include guards.


Reading ahead it looks like this only works because you assume T inherits from Singleton and thus makes sure that all the copy/move semantics are disabled.

    static T& get()
    {
        static T obj;
        return obj;
    }

But your get() method does not validate this. So I could call this method with anything and get a reference to a thing that is not a signelton.

    std::string myString = Singleton::get<std::string>();

You can make sure that the class works correctly by using static_assert.

    static T& get()
    {
        static_assert(std::derived_from<Singelton, T> == true);

        static T obj;
        return obj;
    }

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.