3

(This questions assumes that a global + unique object is the goal. I would like to clarify that this does not mean it is asking about or advocating the if/why/when of using/not-using singletons or globals.)

I am wondering if there's a technicality about C++ that I'm missing, so my question is:

Is a namespace implementation of the singleton pattern in C++ valid? And if so, is there a reason why it is not often suggested as the better approach?

From Google's style guidelines, we see namespace non-member functions recommended over static member function, but only when not sharing static data:

"Rather than creating classes only to group static member functions which do not share static data, use namespaces instead."

Why shy away from letting non-member functions share static data, declared in an unnamed namespace? Is there something wrong about this that explains why namespaces aren't generally suggested as a better alternative to writing a singleton class in C++?

Because I can't find recommendations of the namespace approach, but it is very easy to find the class approach despite C++ not enforcing the use of classes:

C++ Singleton design pattern

Can any one provide me a sample of Singleton in c++?

Singleton instance declared as static variable of GetInstance method

http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

Singleton: How should it be used

Using a named namespace with an unnamed namespace in its source file:

  • You can have 'state' via static data
  • You can gain the extra privacy of putting things in an unnamed namespace
  • You can still control the construction order of its static objects by using static pointers, and constructing from function calls.
  • You don't need to implement a singleton class

Edit - Example of namespace approach I was thinking:

SingleThing.h:

namespace single_thing   // The singleton (if this is actually valid)
{
    void GrowSomeCats(int amount); // Typical setter
    int GetNumCats();              // Typical getter
}

SingleThing.cpp:

#include "Balloon.h"

namespace // Acting like private members and functions
{   
    int numCats = 4;        // POD
    Balloon* wilson = NULL; // Not POD (and not a singleton)

    // Contrived 'private' function
    bool CanGrowCats()      
    { return wilson && wilson->LikesCats(); }

    // Contrived excuse to instantiate non-POD 'members'
    void RandomlyCreateOtherObjects()
    {
        if (!wilson /* && someRandomiserImTooLazyToType()*/ )
            wilson = new Balloon();
    }
}

namespace single_thing  // 'Public' functions
{
    void GrowSomeCats(int amount)
    {
        RandomlyCreateOtherObjects();
        if (CanGrowCats()) 
            numCats += amount;
    }

    GetNumCats()
    { return numCats; }
}
Xenial
  • 465
  • 2
  • 15
  • 1
    This seems to be a question about the merits of object oriented programming, is it worth combining related state and functions into a "class". The fact that it also happens to be a singleton I think is mostly irrelevant. – Chris Drew Oct 21 '17 at 08:46
  • 1
    Note this is not thread safe. I recommend looking up the Meyer's Singleton. – Chris Drew Oct 21 '17 at 08:59
  • Many thanks, both helpful comments. – Xenial Oct 21 '17 at 11:37

2 Answers2

3

(I assume we can agree that global state is a dangerous thing that has to be used with special care.)

Technically your singleton namespace is equivalent to a singleton class. However it has one major drawback that makes it a no-go in my opinion: It hides the fact that it is stateful. Ever used std::strtok()? Remember what an atrocious mess it is? That’s because it hides its statefulness, too.

Because global state is inherently dangerous, any piece of functionality that uses it should make that fact abundantly clear at the call site, preferrably by using language constructs – because nobody reads comments or documentation. A Foo::instance()->do_work(); is a known pattern that makes it quite clear that something special is going on; a foo::do_work(); does not.

besc
  • 2,507
  • 13
  • 10
  • Many thanks for hitting the 2 bolded questions without getting distracted by the singleton/globals assumption. Now I can see that I'm not doing something wrong purely technically, but that there's a meaningful drawback to it. Obligatory disclaimer. Obligatory disclaimer. – Xenial Oct 21 '17 at 11:38
-1

Singleton design pattern is about creation the only instance of a useful class (there is no need in creation of useless objects). In C++ classes are defined with class and struct keywords. To be useful a singleton class, beside creation and destruction, should also implement some methods that operate with the instance. To ensure singularity, a singleton class should hide its constructors and expose a static method for accessing the instance.

Using only namespaces one would not be able to define useful methods of the singleton. Implementing the instance access method as a function in a namespace instead of the class itself is possible, but would require 'friending' that function, and does not make sense because the class is already defined.

Implementing a non-object singleton (e.g. of a plain data type) would assume that the instance does not require construction and thus there is no need for singleton.

hutorny
  • 863
  • 11
  • 17
  • I'm not sure why you say useful methods couldn't be written with the namespace approach. – Xenial Oct 21 '17 at 06:07
  • How do you envision accessing the instance from a namespace function? – hutorny Oct 21 '17 at 06:10
  • (Accidentally hit enter just then.) You have talked in terms of 'the instance' a bit, but I am asking about a namespace approach that doesn't use a particular instance at all. Perhaps it is worth clarifying that my understanding is that singleton is a concept; singleton class is one implementation of it, and I am asking about a different implementation. I'll edit the Q to clarify. :) – Xenial Oct 21 '17 at 06:13
  • If there is no instance, why there would be a need for singleton design pattern? – hutorny Oct 21 '17 at 06:15
  • Question edited to show example of singleton implemented without singleton class/instance. – Xenial Oct 21 '17 at 07:06
  • In this example numCats is a statically allocated instance of int data type. It is initialized (constructed) before execution of any application code. Its singularity is guarantied by the compiler. However, it is not a singleton (by definition of the latter) – hutorny Oct 21 '17 at 07:34
  • The example is showing the entirety of "single_thing" as the singleton; not any of the variables, POD or otherwise. I was explicit about only the non-POD because I thought only that would confuse. – Xenial Oct 21 '17 at 08:06