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.
Related
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.
I have something that looks like this
class RestaurantCheck
{
private:
static const int MENU_LENGTH = 10;
static const string menu[MENU_LENGTH] = {"Gumbo", "Shrimp", etc...}
Right off the bat, I have a problem. I know I can't initialize the data in the array as it is now, so I tried this ...
class RestaurantCheck
{
private:
static const int MENU_LENGTH = 10;
static const string menu[MENU_LENGTH];
void displayMenu();
public:
void showMenu()
{
RestaurantCheck thisMenu;
thisMenu.displayMenu();
}
void RestaurantCheck::displaymenu()
{
menu[0] = "Shrimp"
menu[1] = "Gumbo"
etc...
cout << menu[0]
etc...
However I am unable to store data in the array like that as well.
How the heck am I supposed to store data in this array? As part of the assignment, the array must be a const static, it must be in private, and the displayMenu must also be private, called by a public function.
I hope what I'm getting at is clear, if not I'll try to provide more information.
EDIT:
I can not edit anything from the instructors source file. The source file is already created, and he will be using his own (provided) to test both my class file and my header file. Thus it needs to be initiated outside of sourcefile.
You are falling into the same trap as many before you. Your array is const, so it must be initialized when declared. But you can not initialize static string arrays in the class body. What do you do? You initialize it outside!
like this:
in your .h file:
static const std::string menu[10];
in your .cpp file:
const std::string RestaurantCheck::menu[10] = {"Shrimp", "Calamari", "Listeria"};
Is this what you are looking for?
You can initialize static non scalar members, but this must be done outside the class:
#include <string>
class RestaurantCheck{
static const int MENU_LENGTH = 3;
static const std::string menu[MENU_LENGTH];
};
const std::string RestaurantCheck::menu[RestaurantCheck::MENU_LENGTH] = {"Gumbo", "Shrimp", "Jar" };
note the "init line" must be present only in one file, best place is some .cpp file that is compiled to object. Here is what I mean:
restaurantcheck.h - RestaurantCheck header
restaurantcheck.cpp - RestaurantCheck implementation (best place for "init line")
main.cpp - program (where main() is located)
I am trying to make it possible for a programmer (who uses my library) to create nameable instances of type X that are stored inside an instance of class C (or at least are exclusive to that instance).
These are the only two (ugly) solutions I have managed to come up with (needless to say, I am just picking up C++)
1)
class C
{
public:
class XofC
{
public:
XofC() = delete;
XofC(C& mom)
{
mom.Xlist.emplace_front();
ref = Xlist.front();
}
X& access()
{
return ref;
}
private:
X& ref;
};
//etc
private:
std::forward_list<X> Xlist;
friend class XofC;
//etc
}
Problem:
Having to pass everywhere XofC instances.
2)
class C
{
public:
void newX(std::string);
X& getX(std::string);
//etc.
private:
/*possible run-time mapping implementation
std::vector<X> Xvec;
std::unordered_map<std::string, decltype(Xvec.size())> NameMap;
*/
//etc
}
Problem:
This does the job, but since all names of X (std::string) are known at compilation, the overhead of using run-time std::unordered_map<std::string, decltype(Xvec.size())> kind-of bugs me for something this simple.
Possible(?) solution: compile-time replacing of std::string with automatic index (int). Then I could use:
class C
{
public:
void newX(int); //int: unique index calculated at compile time from std::string
X& getX(int); //int: unique index calculated at compile time from std::string
//etc.
private:
std::vector<X> Xvec;
}
Questions:
Is there a 3)?
Is a compile time solution possible for 2)?
This is the real-life situation: I was starting my first C++ "project" and I thought I could use the practice and utility from an awesome user-friendly, simple and fast argument management library. I plan to make an ArgMan class which can parse the argV based on some specified switches. Switches would be named by the programmer descriptively and the trigger strings be specified (e.g. a switch named recurse could have "-r" and "-recursive" as triggers). When necessary, you should be easily able to get the setting of the switch. Implementation detail: ArgMan would have a std::unordered_map<std::string/*a trigger*/, ??/*something linking to the switch to set on*/>. This ensures an almost linear parse of argV relative to argC. How should I approach this?
You could 'abuse' non-type template arguments to get compiletime named instances:
Live on Coliru
Assume we have a data class X:
#include <string>
struct X
{
int has_some_properties;
std::string data;
};
Now, for our named instances, we define some name constants. The trick is, to give them external linkage, so we can use the address as a non-type template argument.
// define some character arrays **with external linkage**
namespace Names
{
extern const char Vanilla[] = "Vanilla";
extern const char Banana [] = "Banana";
extern const char Coconut[] = "Coconut";
extern const char Shoarma[] = "Shoarma";
}
Now, we make a NamedX wrapper that takes a const char* non-type template argument. The wrapper holds a static instance of X (the value).
// now we can "adorn" a `namedX` with the name constants (above)
template <const char* Name>
struct NamedX
{
static X value;
};
template <const char* Name> X NamedX<Name>::value;
Now you can use it like this:
int main()
{
X& vanilla = NamedX<Names::Vanilla>::value;
vanilla = { 42, "Woot!" };
return vanilla.has_some_properties;
}
Note that due to the fact that the template arguments are addresses, no actual string comparison is done. You cannot, e.g. use
X& vanilla = NamedX<"Vanilla">::value;
becuase "Vanilla" is a prvalue without external linkage. So, in fact you could do without some of the complexity and use tag structs instead: Live on Coliru
While Neil's solution did what I asked for, it was too gimmicky to use in my library. Also, sehe's trick is surely useful, but, if I understood correctly, but doesn't seem related to my question. I have decided to emulate the desired behavior using method 1), here is a less broken attempt at it:
class C
{
private:
class X
{
//std::string member;
//etc
};
public:
class XofC
{
public:
XofC(C & _mom) : mom(_mom)
{
mom.Xlist.emplace_front();
tehX = &(Xlist.front());
}
X & get(maybe)
{
if (&maybe != &mom) throw std::/*etc*/;
return &tehX;
}
private:
X * tehX;
C & mom;
};
private:
//etc
std::forward_list<X> Xlist;
friend class XofC;
//etc
};
Usage:
C foo;
bar = C::XofC(foo); //acts like an instance of X, but stored in C, but you have to use:
bar.get(foo)/*reference to the actual X*/.member = "_1_";
Of course, the downside is you have to make sure you pass bar everywhere you need it, but works decently.
This is how it looks like in my tiny argument manager library:
https://raw.github.com/vuplea/arg_manager.h/master/arg_manager.h
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.
I'm writing some code which could really do with some simple compile time metaprogramming. It is common practise to use empty-struct tags as compile time symbols. I need to decorate the tags with some run-time config elements. static variables seem the only way to go (to enable meta-programming), however static variables require global declarations. to side step this Scott Myers suggestion (from the third edition of Effective C++), about sequencing the initialization of static variables by declaring them inside a function instead of as class variables, came to mind.
So I came up with the following code, my hypothesis is that it will let me have a compile-time symbol with string literals use-able at runtime. I'm not missing anything I hope, and that this will work correctly, as long as I populate the runtime fields before I Initialize the depending templates classes ? .
#include <string>
template<class Instance>
class TheBestThing {
public:
static void set_name(const char * name_in) {
get_name() = std::string(name_in);
}
static void set_fs_location(const char * fs_location_in) {
get_fs_location() = std::string(fs_location_in);
}
static std::string & get_fs_location() {
static std::string fs_location;
return fs_location;
}
static std::string & get_name() {
static std::string name;
return name;
}
};
struct tag {};
typedef TheBestThing<tag> tbt;
int main()
{
tbt::set_name("xyz");
tbt::set_fs_location("/etc/lala");
ImportantObject<tbt> SinceSlicedBread;
}
edit:
Made community wiki.
I've finally understood what the problem was... and your solution does not solve much, if any.
The goal of using local static variable is to provide initialization on first use, thus being safe from the "Initialization Order Fiasco" (by the way, it does not solve the "Destruction Order Fiasco").
But with your design, if you effectively prevent the crash you do not however prevent the issue of using a variable before its value is used.
ImportantObject<tbt> SinceSliceBread; // using an empty string
tbt::set_name("xyz");
Compare with the following use:
std::string& tbt::get_name() { static std::string MName = "xyz"; return MName; }
Here the name is not only created but also initialized on first use. What's the point of using a non initialized name ?
Well, now that we know your solution does not work, let's think a bit. In fact we would like to automate this:
struct tag
{
static const std::string& get_name();
static const std::string& get_fs_location();
};
(with possibly some accessors to modify them)
My first (and easy) solution would be to use a macro (bouh not typesafe):
#define DEFINE_NEW_TAG(Tag_, Name_, FsLocation_) \
struct Tag_ \
{ \
static const std::string& get_name() { \
static const std::string name = #Name_; \
return name; \
} \
static const std::string& get_fs_location() { \
static const std::string fs_location = #FsLocation_; \
return fs_location; \
} \
};
The other solution, in your case, could be to use boost::optional to detect that the value has not been initialized yet, and postpone initialization of the values that depend on it.