Avoiding the whole discussion of whether Singleton is a good to have pattern or the source of all evil, if you are actually implementing a singleton, chances are that const correctness will not work there as you expect it, so you should be aware of some pitfalls.
First your error: your Instance()
static member returns a const reference, and that means that you can only perform operations that do not modify the object, i.e. call member functions marked as const
, or use public members if present in a way that do not modify their values. My suggested solution is modify Instance()
to return a non-const reference, rather than making func()
const as others suggest.
Now for a longer explanation to the problem of const-correctness in general when applied to your particular Singleton problem. The basic problem is that when you implement a type, you divide those members that modify the object from those that don't, and you mark the latter as const
member functions so that the compiler knows of your promise (allows you to call that method on a constant object) and helps you not break it (complains if you try to modify the state in the definition of the method). A method that is marked as const
can be applied to both a constant and non constant object, but a method that is not marked const
can only be applied to an object that is not const
.
Back to the original piece of code, if you implement a singleton and the only way of accessing the object is by an Instance()
method that returns a const
reference, you are basically limiting all user code to use only const
methods implemented in your interface. That means that effectively either all methods are non-mutating, or they are useless (const_cast
should never be used). That in turn means that if you have any non-const operation you want to provide an Instance()
method that returns a non-const reference.
You could consider implementing two variants of Instance()
, but that will not be really helpful. Overload resolution will not help in user code to determine which version to use, so you will end up having to different methods: Instance()
, ConstInstance()
(choose your names), which means that it is up to user code to determine which one to use. The small advantage is that in their code, the choice of accessor will help documenting their intended usage, and maybe even catch some errors, but more often than not they will just call the non-const version because it works.