static string constants in class vs namespace for constants [c++] - 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.

Related

How To Declare Static Const Array

I coded like this in class with public modifier:
static const string brands[] = {"Coca-Cola","Pepsi","Ruffles"};
And it gives me this error code:
E1591
How can I solve that ?
As far as I know you can't have in-class initializer for your static const std::string [].
You should initialize it outside the class declaration.
For instance:
#include <string>
class Foo
{
public:
static const std::string brands[];
};
// in your Foo.cpp file
const std::string Foo::brands[] = {"Coca-Cola","Pepsi","Ruffles"};
The C++ answer is to skip using C arrays, which have limitations in C++ not present in C, and instead use std::vector:
static const std::vector<std::string> brands = {"Coca-Cola","Pepsi","Ruffles"};
Note the std:: prefix which should be present as using namespace std can be highly problematic for a variety of reasons, most of all name conflict. The prefix exists for a reason.

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

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.

Creating a centralized variable file

I am working on a self organizing map program.
For it i am trying to create a way that I can centralize all the user/developer variables that can be set. I have been trying to use a Config.h/.cpp files but am unsure if this is the correct/best method.
It seems if I don't put things in in just the right way it errors on compile.
The question is the best/correct way to centralize variables that must be changed in between compilation and runs?
Config.h
#ifndef CONFIG_H_
#define CONFIG_H_
class Config{
public:
static const std::string outputFileLocation;//
static const std::string inputFilename;//
static const std::string outputFileExt;//
unsigned int vectorLength = 3;//RGB
//VARIBLE USED IN SOM CLASS
static const int NODE_GRID_HEIGHT = 100;
static const int NODE_GRID_WIDTH = 100;
};
#endif /* CONFIG_H_ */
Config.cpp
#include "Config.h"
//location to store output soms at it is iterated through
std::string Config::outputFileLocation = "/home/projectFiles/testMedia/results/mySom_";
//extension to put on output soms.
std::string Config::outputFileExt = ".jpeg";
////starting rgb image file to proccess
std::string Config::inputFilename = "/home/projectFiles/testMedia/yellowColor3.jpg";
////Length of muliti-dimensional data point. ie. a pixel.
unsigned int Config::vectorLength = 3;
It's a valid approach to keep the config in a distinct class. So you will be able to define a constructor for a default configuration, as well as config load and save methods.
However in you code there are minor consistency issues.
If you declare :
static const std::string outputFileLocation; // you said const
Then you should define it as a const :
const std::string Config::outputFileLocation = "/home/projectFiles/testMedia/results/mySom_";
Conversely, if you define a non static data member:
unsigned int vectorLength = 3; //You already intialise it here
You shall not redefine it as you did. This would only be necessary for statics.
However, I wonder why you make the statics const. This requires that they are initialised (either as you did, if they are static, or as part of the constructor for ordinary members) and they may not change afterwards. This prevents your from changing the configuration, for example when loading a config file at startup.
Additional thoughts
Once you have your configuration class, you can decided easily which variable is fixed at compilation, and which should be initialised dynamically. Dynamically could for example be:
read a configuration file (see: this SO question).
get some variables through system environment (see getenv())
system specific approaches, but this woudld not be portable so should be considered with care (for windows, it's usual for example to use the registry)
using command line arguments passed to main().
I deduce you are using your code to run experiments, since you need to change variables values between compilations and runs. One simple way I have done this in the past is by centralizing everything inside an unnamed namespace in a header file. This way, you may drop the static declarations, and just #include the config file where you need.
Something like this.
Configs.h
#ifndef CONFIG_H_
#define CONFIG_H_
namespace{
const std::string outputFileLocation = "something";//
const std::string inputFilename = "something";//
const std::string outputFileExt = "something";//
unsigned int vectorLength = 3;//RGB
//VARIBLE USED IN SOM CLASS
const int NODE_GRID_HEIGHT = 100;
const int NODE_GRID_WIDTH = 100;
};
#endif
Note this might not be the best solution, but is simple and effective. Depending on the goals of your project, you might need to consider a more elegant solution.
Another suggestion
Assuming my deduction is correct, reading those values from a configuration text file would also be a good option. You would not need to recompile between runs, which may be very time consuming if you have a large project, and many other files depend on that single configuration one.

How to correctly write declarations of extern arrays in C's header files?

First of all, let me confess that pointer-to-an-array always gets me confused. Hence, I am asking this question.
Suppose I want to share a global array of data across my program, for example:
static const char * EnumStrings_WIP_Selection_Box[] = { "Rectangular", "Siemens Gauss", "My_Gauss", "Planck-Taper", "Invalid"};
When I try to declare corresponding “extern” command
extern static const char * EnumStrings_WIP_Selection_Box[];
or
extern static const char * EnumStrings_WIP_Selection_Box[5];
I get the following error
error C2159: more than one storage class specified
Also, can someone also tell me the different between these?
Foo *array[10];
Foo (*array1)[10];
Any help would be appreciated.
I've assumed you want you array to be "totally" constant, as many people aren't aware of the two-consts on a pointer. This means not only can the text pointed to by the array not change, the pointers in the array also cannot be changed to point to new text.
You should make sure the data in your array is defined in a source file, or you risk a copy of the data in memory for every source file that includes the header.
Header file
extern const char *const MyText[];
Source file
extern const char *const MyText[] = { "Hello", "There"; };
Alternatively, the C++ approach
Header file
extern const std::vector<std::string> MyText;
Source file
extern const std::vector<std::string> MyText = { "Hello", "There"; };
To force it all in one file (not recommended in a header file)
const char *const MyText[] = { "Hello", "There"; };
extern and static are both storage classes, and are mutually exclusive.
Don't specify them together. You want:
extern const char * EnumStrings_WIP_Selection_Box[];
The static conflicts with the extern.
Try this:
.cpp file:
/* not static */
const char * EnumStrings_WIP_Selection_Box[] = { "Rectangular",
"Siemens Gauss", "My_Gauss", "Planck-Taper", "Invalid"};
.h[pp] file:
extern const char * EnumStrings_WIP_Selection_Box[];
That said, for the sake of future maintainers, please consider defining your access in terms of methods, not exposed pointers (i.e. consider adding a char const * const GetWipSelectionByIndex(const std::size_t index) to your public API, instead of exposing an array).

C++ Class Common String Constants

In C++ I would like to define some strings that will be used within a class but the values will be common over all instances. In C I would have used #defines. Here is an attempt at it:
#include <string>
class AskBase {
public:
AskBase(){}
private:
static std::string const c_REQ_ROOT = "^Z";
static std::string const c_REQ_PREVIOUS = "^";
static std::string const c_REQ_VERSION = "?v";
static std::string const c_REQ_HELP = "?";
static std::string const c_HELP_MSG = " ? - Help\n ?v - Version\n ^^ - Root\n ^ - Previous\n ^Z - Exit";
};
int main(){AskBase a,b;}
If C++0x is needed that is acceptable.
You will have to define them separately in a single translation unit (source file), like so:
//header
class SomeClass
{
static const std::string someString;
};
//source
const std::string SomeClass::someString = "value";
I believe the new C++1x standard will fix this, though I'm not entirely sure.
When I need string constants within a class, I never put them in the class itself, but either:
1) If they need to be exposed in the header, I put them outside of the class (in a namespace if appropriate), like this:
const char * const c_REQ_ROOT = "^Z";
...
2) If not, I put them in the cpp file, in an anonymous namespace.
You can then even group strings constant from several related components in the same header file.
It may be not the most "academic" way, but the code is simpler and easier to refactor. I never found any actual advantage of defining string constant as static class members.
I'm really interested by the opinion of other programmers here, so do not hesitate to leave your comments.
I would never use that construction.
If one of the developers refactors the code and starts writing:
// header
class StringBug
{
static const std::string partOfTheString;
static const std::string wholeString;
};
// source
const std::string StringBug::partOfTheString = "Begin ";
const std::string StringBug::wholeString = partOfTheString + "and the rest";
You have a very hard to find bug in the program because there is no garante that partOfTheString is initialized before it is used for the creation of wholeString;
If I want to create class common string I do it like this:
// header
class StringBug
{
static const std::string& partOfTheString() {
static const std::string sPartOfTheString("Begin ");
return sPartOfTheString;
}
static const std::string& wholeString() {
static const std::string sWholeString( partOfTheString() + "and the rest");
return sWholeString;
}
};
According to the Wikipedia article this should be supported in C++0x however I can't find the reference in the State of C++ Evolution page.