11

I am working on a game and have an interesting question. I have some game-wide constant values that I want to implement in one file. Right now I have something like this:

constants.cpp

extern const int BEGINNING_HEALTH = 10;
extern const int BEGINNING_MANA = 5;

constants.hpp

extern const int BEGINNING_HEALTH;
extern const int BEGINNING_MANA;

And then files just #include "constants.hpp" This was working great, until I needed to use one of the constants as a template parameter, because externally-linked constants are not valid template parameters. So my question is, what is the best way to implement these constants? I am afraid that simply putting the constants in a header file will cause them to be defined in each translation unit. And I don't want to use macros.

Thanks

rlbond
  • 65,341
  • 56
  • 178
  • 228

8 Answers8

19

Get rid of the extern and you're set.

This code works perfectly fine in a header, because everything is "truly constant" and therefore has internal linkage:

const int BEGINNING_HEALTH = 10;
const int BEGINNING_MANA = 5;
const char BEGINNING_NAME[] = "Fred";
const char *const BEGINNING_NAME2 = "Barney";

This code cannot safely be put in a header file because each line has external linkage (either explicitly or because of not being truly constant):

extern const int BEGINNING_HEALTH = 10;
extern const int BEGINNING_MANA = 5;
const char *BEGINNING_NAME = "Wilma";  // the characters are const, but the pointer isn't
Tom
  • 10,689
  • 4
  • 41
  • 50
10

How about enums?

constants.hpp

  enum {
    BEGINNING_HEALTH = 10,
    BEGINNING_MANA = 5
  }
Tommy Hui
  • 1,306
  • 6
  • 9
7

Use "static const int" in your .hpp file, and put nothing in the .cpp file (except whatever other code you have there of course).

Jim Buck
  • 20,482
  • 11
  • 57
  • 74
4

make use of namespaces:

namespace GameBeginning {
    const int HEALTH = 10;
    const int MANA   = 5; 
};

then u can use as player.health = GameBeginning::HEALTH;

user77682
  • 49
  • 1
0

Most compilers simply don't allocate space for const POD values. They optimize them out and treat them as if they had been #defined, don't they?

greyfade
  • 24,948
  • 7
  • 64
  • 80
  • Close, but still not quite the same. Example where macros work but constants don't: #define FOO "foo"; \ const char *str = "bar" FOO; C and C++ allow concatenation of string literal tokens, but not string constants. – Tom Mar 13 '09 at 04:40
  • This is only true for integral constants. Floats, doubles, char*s, and other types will be allocated storage if optimization is disabled. – Adam Rosenfield Mar 13 '09 at 04:46
  • @Tom: That's not what I meant. I meant for POD constants, not preprocessor majicks. I meant in the sense that the symbol and the space for the value don't exist unless you attempt to take its address. – greyfade Mar 13 '09 at 06:12
  • I think POD officially includes floats and doubles, but floats and doubles are generally not optimized in this way. – Max Lybbert Mar 13 '09 at 08:52
0

What ever happened to a simple:

#define BEGINNING_HEALTH 10

Man, those were the days.
Oh wait, those still are the days!

slacy
  • 11,397
  • 8
  • 56
  • 61
-2

perhaps something along the lines of a static class?

class CONSTANTS {
public:
static inline int getMana() { return 10;};
};
MighMoS
  • 1,228
  • 8
  • 18
  • That doesn't help. Function values cannot be used as template parameters. C++0x keyword `constexpr` is supposed to work around that. Besides, C++ has namespaces, which are superioer to a static class for "namespacing" constants. – Tom Mar 13 '09 at 04:06
-5

As a quick answer to the title question, a singleton pattern is a possible best, C++ way to define cross-file constants and insure only one instance of the object.

As far as the template parameter problem, you need to pass a type not a value. Your type is "int".

jeffD
  • 1,230
  • 3
  • 13
  • 18
  • 1
    This seems like overkill for a set of simple constants, and is not likely to solve his problems with template instantiation. – Eclipse Mar 13 '09 at 04:15
  • Why wouldn't is solve his problem with template instantiation, since it wouldn't be an extern, it would be a local. Overkill is relative, what is the quality perspective $100M, $100K, or $100 game budget? – jeffD Mar 13 '09 at 06:26
  • jeffD, the problem is that your answer does not make sense. do you want to make an "int" a singleton? an int is comprised by value, not by identity. another thing that probably made people downvote you is that he doesn't want to pass a type, but a value to his template. Why do you say he can't? – Johannes Schaub - litb Mar 13 '09 at 06:44
  • The title to the question is a good question by itself. Maybe I do need to see more of his code. See http://www.cplusplus.com/doc/tutorial/templates.html for a ref. "A template parameter is a special kind of parameter that can be used to pass a type as argument". Wish comments allowed hyperlinks. – jeffD Mar 13 '09 at 06:55
  • Nice, the http address automatically becomes hyperized. – jeffD Mar 13 '09 at 07:02
  • jeffD, unfortunately, the tutorial at cplusplus.com isn't quite good - too incomplete and sometimes wrong. for example template declarations are not "expressions" as they say, they are declarations. blurs out the difference between a specialization and an explicit specialization on their page too. – Johannes Schaub - litb Mar 13 '09 at 07:47
  • better get a good book (there are some good threads on SO about C++ books) rather than relying on cplusplus.com . even for a reference, it has some quite blatantly wrong pages (i wonder whether they still maintain them?). and please read the very end on that linked page (about non-type parameters). – Johannes Schaub - litb Mar 13 '09 at 07:49
  • For the record, you can pass integral values to templates (Boost.Array uses this ability, I believe). – Max Lybbert Mar 13 '09 at 08:54
  • jeffD, I have a Matrix class that is uses a static array. Its class signature is template class Matrix. This is perfectly legal C++ code. – rlbond Mar 13 '09 at 16:09
  • I stand by my answer to the title question. You may be right about what he's doing w/ templates, w/o seeing the code and error it's unsure. There are really two questions here, I think I'll pose one as a seperate question. – jeffD Mar 13 '09 at 17:05