To singleton or not to singleton, that is the question....
-
@JonB said in To singleton or not to singleton, that is the question....:
should have been declared inside ‘RandomNumber’
This should work (in .cpp):
void someHelperFunction() { } namespace RandomNumber { void foo() { someHelperFunction(); } }
-
@JonB said in To singleton or not to singleton, that is the question....:
consequently as well having to put in whatever #includes into the .h just to support anything in private
In case of pointers you can avoid the includes by using forward declarations.
Often d pointer pattern is used to hide implementation details and keep binary compatibility while changing internal implementation.
-
@jsulm
Hi, not sure if you are adding something here? I wrote above that, with nothing in the.h
file, you can indeed put in the .cpp
namespace RandomNumber { void foo() { ... } }
What I said I found you cannot do is
void RandomNumber::foo() { ... }
For that, if you are not going to put
namespace RandomNumber { void foo(); }
in the
.h
(because you want to only use it privately) then I found you can/must add it in the.cpp
--- this adding to thenamespace
declarations from the.h
--- before defining it viavoid RandomNumber::foo() { ... }
.[I never had a question about some global/free
someHelperFunction()
function.] -
@jsulm said in To singleton or not to singleton, that is the question....:
In case of pointers you can avoid the includes by using forward declarations.
Of course, and I do sometimes do that to avoid being forced to pull in a full
#include
. But when, say, you have a whole load ofprivate
methods in a class and they use types (copy or reference) as parameters/returns which are either from your own "internal" types or from external types you get forced to have the full#include
s in the.h
even if only relevant to yourprivate
methods. I hate that. -
@JonB said in To singleton or not to singleton, that is the question....:
then I found you can/must add it in the .cpp --- this adding to the namespace declarations from the .h
One of the nice things about namespaces is that you can reopen them as often as you want to. There are even a few cases where you are supposed to add something to namespace
std
.@JonB said in To singleton or not to singleton, that is the question....:
they use types (copy or reference) as parameters/returns
Just like pointers, references are also find and just need forward declarations. If your class has more than one or two member variables (of built-in type) it is most likely cheaper to use a reference instead of a copy. I only have very few cases where I'd want a copy of an object. That being said, I just noticed that I don't know if r-value references
&&
also work with forward declarations. Does anybody know? -
@SimonSchroeder r-value references && work with forward declarations.
-
@jsulm if void baz() is defined in two namespaces, Calling baz() with using "using Foo;" can cause confusing while two namespaces are present at the same place. Therefore, Foo:: prefix is preferred.
namespace Foo1 { void baz() { ... } } namespace Foo2 { void baz() { ... } } In another class: using Foo1; using Foo2; void AnotheClass::testing() { baz(); // not clear } =================== void AnotheClass::testing() { Foo1::baz(); // clear }
-
I agree that in general you should avoid
using
(for namespaces; now also allowed as a replacement fortypedef
).There are, however, a few select places where I do use it for namespaces: 1) When using
swap
the preferred method is tousing std::swap;
(technically not a namespace) and then callswap
unqualified (without a namespace, class name, etc). 2) For using string""s
and string view""sv
literals. Haven't usedstd::chrono
much, but most likely would import the suffixes as well. -
@JoeCFD said in To singleton or not to singleton, that is the question....:
Calling baz() with using "using Foo;" can cause confusing while two namespaces are present at the same place.
In the concrete example you have given, it would not compile because the compiler cannot resolve the overload (i.e. Foo1::baz or Foo2::baz). You'd still need to use a fully qualified name. It only gets confusing when you have
Foo1::baz(int)
andFoo2::baz(double)
. You might writebaz(1);
when you actually want to call Foo2::baz. The software might even do the right thing for years. Someone might just introduce Foo1::baz years down the line and suddenly the behavior changes.