Is it correct to define a global std::string in a header file like this :
namespace Colors
{
    static const std::string s_blue = "Blue";
}
Is it correct to define a global std::string in a header file like this :
namespace Colors
{
    static const std::string s_blue = "Blue";
}
 
    
    Yes. static here means that each translation unit (TU) that includes this header will have a unique object. So there isn't 1 s_blue object for the whole project, but one for each TU.
However since it's const all objects will be equal, so for the user it doesn't make a difference.
Maybe, depends.
The big downside is that you create multiple objects and all of them are initialized at program startup.
Another possible downside is the access pattern. If the program assesses s_blue from multiple TUs in quick succession it could trash the cache.
However for certain programs and scenarios this could be the best option or at least "good enough". For instance (spoiler for next paragraph) in a header only library or before C++17.
Yes, but they cannot always be used.
externMake it an extern declaration in the header and in just 1 TU have the definition.
// constants.hpp
extern const std::string k_blue;
// constants.cpp
#include "constants.hpp"
const std::string k_blue = "Blue";
This is clearly superior in terms of performance over OP. However you can't use it in a header only lib.
Even in a normal program static could be preferred as the ease of declaring and defining the constants in just one place could be seen as outweighing the performance downsides in specific projects.
constexpr inline string_view C++17A clearly better alternative if it's available (since C++17) is string_view. It's very light weight but has all the amenities of a modern container (unlike raw const char[]). And since you already are in C++17 you should make it constexpr inline:
constexpr inline std::string_view k_blue = "Blue";
inline const std::string c++17If for whatever reason you need std::string over std::string_view you can inline the variable for better optimization:
inline const std::string k_blue = "Blue";
 
    
    Note that static in namespace level means: "symbol is visible only for current translation unit."
Also const at namespace level defaults to static so this keyword is not needed.
So every time you will include this file you will have new instance of this variable. Liker will not complain that there is multiple instances of this symbol.
If you are using C++17 it would be better to use std::string_view and constexpr:
namespace Colors
{
    constexpr std::string_view s_blue = "Blue";
}
