Should I prefer static const variables at class or namespace scope? - c++

Does one have any tangible benefits over the other? I've started using the latter because it doesn't pollute the header file with static const declarations, so it's a bit easier to read. I'm often using these constants in only a couple of member functions.
Class scope:
.hpp
class MyType
{
private:
static const std::wstring kFoo;
}
.cpp
const wstring MyType::kFoo(L"foo");
...
void MyType::parse(const wstring& input)
{
if (input == kFoo) { do1; }
...
}
versus
namespace scope
.cpp
const wstring kFoo(L"foo");
...
void MyType::parse(const wstring& input)
{
if (input == kFoo) { do1; }
...
}

First of all,
const wstring kFoo(L"foo");
is in global scope, not in a namespace. You can easily wrap that in an anonymous namespace.
namespace
{
const wstring kFoo(L"foo");
}
Coming to the question of whether it is better to use static member of the class or a member in a namespace, the answer depends on team coding style guidelines as well as personal preferences.
My suggestion would be to put it under the anonymous namespace in the .cpp file. That way, it can remain an implementation detail and the class definition is not polluted by an implementation detail.
PS
Please note that the question static string constants in class vs namespace for constants [c++] addreses the issue but with a difference. In the other post, the user wants to share the static member variable across multiple files. In your post you have explicitly put the static member variable as a private member, and hence not to be shared acrosss files. If that assessment is incorrect, your question is a duplicate of the other question and deserved to be closed as such.

Related

What is the difference between declaring a static variable in a class in the .h file and a "global" variable in the .cpp file

I don't know if my title is expressed with the right terminology, if it isn't, please correct me so I can update it. However this is my question expressed with code examples: What is the difference, when it comes to the keyStates variable, between example A and B?
Example A (Where the "keyStates" variable is defined as a static variable in the class in the .h file):
// Input.h
class Input
{
public:
static bool GetKeyDown(KeyCode keycode);
private:
static std::unordered_map<KeyCode, KeyState> keyStates;
}
// Input.cpp
#include "Input.h"
bool Input::GetKeyPressed(KeyCode keyCode)
{
for (auto Code : AllKeyCodes)
{
if (Code == keyCode)
{
return KeyState::PRESSED == keyStates.find(Code)->second;
}
}
return false;
}
Example B (Where the "keyStates" variable is defined without static in the .cpp file):
// Input.h
class Input
{
public:
static bool GetKeyDown(KeyCode keycode);
}
// Input.cpp
#include "Input.h"
std::unordered_map<KeyCode, KeyState> keyStates;
bool Input::GetKeyPressed(KeyCode keyCode)
{
for (auto Code : AllKeyCodes)
{
if (Code == keyCode)
{
return KeyState::PRESSED == keys.find(Code)->second;
}
}
return false;
}
Well, when you have a static member of a class (whether it's a field or a method), it is "global" for the whole class, so that:
To access it from anywhere you need to use ClassName::method() or ClassName::field.
You can share or restrict access to this member with access modifiers: private, public and ptorected.
This member belongs to the class, not to any specific objects. You cannot use this from such methods
The full list of restrictions is there: https://en.cppreference.com/w/cpp/language/static
The static global variable, on the other hand, is like a usual global variable, except it "exists" only for the current compilation unit. You can not use it from anywhere except this particular .cpp file.
With a usual global variable if there are two compilation units (cpp files) with the same global variable int a, the code won't compile. Here is more on that: C/C++ global vs static global
Also, you can use anonymous namespaces anywhere where you would use static global variables (or methods, or even types).
UPD.: Yet another difference here. When you put your keyStates into cpp file as a static global (or part of anonymous namespace), the implementation detail is hidden from class definition and the .h file. So you can change it whenever you wish w/o changing the interface and having to recompile anything except the cpp file.

Is there a way to avoid constexpr function used in header file from entering global scope without extra namespace for it?

I have a header file with code simply looking like this:
constexpr uint32 GenTag(const char tag[5]) { ... }
class SomeClass
{
static constexpr uint32 TAG1 = GenTag("smth");
static constexpr uint32 TAG2 = GenTag("abcd");
};
//constexpr needed for switch-case statement
The problem is that function GenTag() belongs to global scope and I would like to avoid it if possible.
I wanted to declare it inside class but it is not possible with constexpr (explanation here: constexpr not working if the function is declared inside class scope).
Does c++ have anything like "undeclare" function at the end of the header (maybe some macro tricks)? Or any other options I missed? If no better ways exist I would probably go with extra (maybe excessive) namespace, but want to ask if there are any other ideas.
There's no way to "undeclare" a function or variable in C++ (header file or not -- a header file is just included into the current translation unit). You'll need to use a namespace, or make GenTag into a macro. You can undefine macros with #undef MACRONAME.
What about defining GenTag() as a static constexpr method in an inherited struct?
If you want that GenTag() is usable only inside SomeClass, you can make it private and define SomeClass as friend inside the class containing GenTag().
I mean... something as follows
#include <iostream>
struct SomeClass;
class foo
{
static constexpr char GenTag(const char tag[5])
{ return tag[0]; }
friend SomeClass;
};
struct SomeClass : public foo
{
static constexpr char TAG1 = GenTag("smth");
static constexpr char TAG2 = GenTag("abcd");
};
int main()
{
std::cout << "Tag1: " << SomeClass::TAG1 << std::endl;
std::cout << "Tag2: " << SomeClass::TAG2 << std::endl;
// compilation error: 'GenTag' is a private member of 'foo'
// static constexpr char TAG3 = foo::GenTag("wxyz");
}
With the friend trick, you don't need to inherit from foo; but, without inheritance, you have to use it as foo::GetTag().
If anyone ever will also meet a problem like this I would recommend you to not use such constexpr in header at all but consider to declare-define it directly in and only in cpp file instead. Then you will definitely avoid unnecessary global scope pollution.
Or if there are multiple places where such constants can be used then make a separate heared for them without any classes and include that file separately from including class definition header.

Private namespace in source files

I have a doubt regarding private methods & functions.
Let's say I have some utility methods that needn't be inside a class. But those same methods need to call other ones that I don't want to expose to the user. For example:
Suspect.h
namespace Suspect {
/**
* \brief This should do this and that and more funny things.
*/
void VerbalKint(void); // This is for you to use
}
Suspect.cpp
namespace Suspect {
namespace Surprise {
/**
* \brief The user doesn't need to be aware of this, as long
* the public available VerbalKint does what it should do.
*/
void KeyserSoze(void) {
// Whatever
}
} // end Surprise
void VerbalKint(void) {
Surprise::KeyserSoze();
}
}
So, this layout works. When including the Suspect.h, only VerbalKint is visible.
This can be as well achieved using a class and marking VerbalKint as static:
class Suspect {
public:
// Whatever
static void VerbalKint(void);
private:
static void KeyserSoze(void);
};
I would like to know if there's any difference between the two approaches. Is one better (faster, easier to maintain) than the other?
What are your thoughts?
If the functions are 'free', you should use an anonymous namespace in the *.cpp:
namespace Suspect {
namespace Surprise {
namespace {
void KeyserSoze(void) {
// Whatever
}
} // end anon
} // end Surprise
} // end Suspect
or even:
namespace {
void KeyserSoze(void) {
// Whatever
}
} // end anon
This keeps it away from clients so they cannot access, depend on, or collide with your exports when linking. It also keeps unnecessary declarations from them, reducing their compile times and potentially link times or binary sizes if definitions are visible. Finally, it makes it private so they cannot depend on it and you do not need to maintain it for their use. You can still pass these to the outside world, if you choose (function pointer in KeyserSoze()'s case).
At other times, it is preferable to declare a private member function in your class then define it in the *.cpp (where possible). Typically, you would opt for this approach when you need a closer relationship with the class (e.g. when you need access to some members). You said this was not the case in the question, but I'm just reiterating when private members should be used.
The best approach is to define all helper functions in an unnamed namespace in Suspect.cpp, instead of in the Suspect::Surprise namespace.
In your case, this would be:
namespace{
void KeyserSoze(){ ... };
}
You can simply call KeyserSoze without any namespace specifiers from within Suspect.cpp.
You can find more information about that here: Unnamed/anonymous namespaces vs. static functions
Another alternative is to declare KeyserSoze to be static, but this is not advised by the standard. The C++ Standard reads in section 7.3.1.1 Unnamed namespaces, paragraph 2:
The use of the static keyword is deprecated when declaring objects in a namespace scope, the unnamed-namespace provides a superior alternative
Actually, even though the function is not visible to the eye when you do not declare it in any header; it still is available to the user should they write the declaration.
In C++, the mechanism to hide symbols declared at file level is:
static for (global) variables and functions
namespace { ... } (anonymous namespaces) for anything you wish (more general, more verbose)
For example:
// Suspect.cpp
namespace Suspect {
static void KeyserSore() {}
void VerbalKing() { KeyserSore(); }
}
The main difference between putting something in a class or a namespace is that you can't add extra static functions to a class in another header file.
This:
a.h
namespace Fred {
void Somefunc();
}
b.h
namespace Fred {
void Anotherfunc();
}
work, although neither a nor b know what each other has done to their namespaces. This could conceivably cause problems, such as this:
c.h
namespace Fred {
void Thirdfunc();
}
d.h
namespace Fred {
bool Thirdfunc();
}
which is all fine and dandy until you get to run the program...
This is, whilst not impossible, a lot less likely with classes.
In your example, with only one source file, you might also want to consider using the anonymous namespace as that restricts declarations to file scope, so people outside your file can't access them (or clash with them) by accident.

c++ variable visibility

PLEASE READ THE SECOND EDIT FIRST.
I am looking for books or websites that explain in detailed the c/c++ memory management models. One of the things I am trying to understand is:
namespace A {
SomeClass A;
}
vs
namespace A {
static SomeClass A;
}
vs
SomeClass A;
vs
static SomeClass A;
Thank you very much.
EDIT:
Sorry for the confusion, I mixed the concepts together, and asked the wrong questions.
Namespaces allow to group entities like classes, objects and functions under a name. This way the global scope can be divided in "sub-scopes", each one with its own name.
You use keyword using to introduce a name from a namespace into the current declarative region.
For example:
without using namespace you will write:
#include
int main () {
std::cout << "Hello world!\n";
return 0;
}
However you can also write:
#include
using namespace std;
int main () {
cout << "Hello world!\n";
return 0;
}
This allows you not to append napespace identifier before every
In C++ static class has no meaning unlike other OOP languages. You can have static data members methods.
Instead you can create:
1.A static method in class
class SomeClass
{
public: static void myMethod(int x..)
{
}
}
2.Create a free function in namespace
namespace A
{
void myMethod(int x..)
{
}
}
Latter is better suited when you do not need an object. No class no object...
In both cases enclosing a class within namespace allows you to to group entities under a common name.
First, namespaces are only known until compilation, after that they're non-existant. That said, your first half is no different from your second half in the final program, at least as far as I know. Correct me if I'm wrong please.
Then, if both static SomeClass A and SomeClass A are at global scope (file level), then they're the same too.
Next, if both declarations are inside of a class, struct or function, then the static version will be put into the data segment of the executable too, while the non-static variant will be a normal stack variable.
Again, please, correct me if I'm wrong, but that's it as far as I know it.

static string constants in class vs namespace for constants [c++]

I want to declare string constants that will be used across various classes in the project. I am considering two alternatives
Option 1:
#header file
class constants{
static const string const1;
};
#cpp file
const string constants::const1="blah";
Option 2:
#header file
namespace constants{
static const string const1="blah";
};
Just wondering what would be a better implementation.
Already looked at
Where to store Class Specific named constants in C++
Where to put constant strings in C++: static class members or anonymous namespaces
UPDATE:
Option 3:
Based on the suggestions from "potatoswatter" and "sellibitze" i currently have the following implementation?
#header file
namespace constants{
extern const string& const1(); //WORKS WITHOUT THE EXTERN ***WHY***
};
#cpp file
namespace constants{
const string& const1(){static string* str = new string ("blah"); return *str;}
}
I'm including the header file where i need to use the constants. Are there any major cons of this implementation?
Update 2 years later:
Every global accessible by more than one source file should be wrapped in an inline function so the linker shares the object between the files, and the program initializes it properly.
inline std::string const &const1() {
static std::string ret = "hello, world!";
return ret;
}
The inline function is implicitly extern and may be wrapped in a named namespace or a class, if you like. (But don't use a class just to hold static members, as namespaces are better for that. And don't use an anonymous namespace as that would defeat the linker, and each source would see a different std::string object.)
All answers that resort to std::string run the risk of dynamically allocating memory for a string literal which is going to remain constant throughout the lifetime of the program (and the binary), so they should be avoided.
sellibitze's answer comes close but it has the problem of declaring it once and then defining it elsewhere, which I don't find elegant and is more work. The best way would be
namespace constants {
const char * const blah = "blah!"
const char * const yada = "yada yada!"
}
This is solution is discussed further here.
Neither. I'd go with this:
// header file
namespace constants {
extern const char const1[];
}
// cpp file
namespace constants {
extern const char const1[] = "blah";
}
The header file contains a declaration of const1 with incomplete type but convertible to char const* and the cpp-file contains a definition of the character array with external linkage. There is no dynamic initialization like you have with std::string. So, that's a plus, IMHO.
Option 1 achieves the same as Option 2, but in a messier way.
If you're going to use a class that just has static members, especially for global access/constants, use a namespace.