I recently came across code which was similar to the following:
#include <stdio.h>
class Example {
private:
enum {
BufSize = 4096,
MsgSize = 200 * 1024,
HeaderFieldLen = 16
};
public:
int getBufSize() {
return BufSize;
}
};
int main() {
Example ex;
printf("%d\n", ex.getBufSize());
return 0;
}
A class was essentially storing constants in an enum and using their values in its member functions.
Is this a valid use of an enum and if so, is there any reason to store constants in this way, as opposed to in a struct or as regular const class member variables?
There are several ways of naming numerical constants in order to avoid magic numbers. Using enumerators are one of them.
The advantage of this method over regular const variables is that enumerators are not variables. Therefore, they are not stored as variables during run-time, they are simply used by the compiler, at compile-time.
[from the comments]
So this usage would be in some ways similar to using preprocessor macros to define constants?
The downside of macros is (mainly) type safety. Macros have no type, so the compiler cannot check for you whether the types match where you use them. Also, while macros are used in C, they are very rarely used in C++ because we have better tools at our disposal.
In C++11, a better way to name these constants is to use constexpr members.
constexpr int BufSize = 4096;
constexpr int MsgSize = 200 * 1024;
constexpr int HeaderFieldLen = 16;
The above code replaces the following.
enum {
BufSize = 4096,
MsgSize = 200 * 1024,
HeaderFieldLen = 16
};
It's valid.
In the early days, not all compilers support static const data member very well. So you have to use this enum hack to simulate a static const integer data member.
Now, since compilers have supported static const data member very well, you don't have use this hack.
// in example.h
class Example {
static const int BufSize = 4096;
};
// in example.cpp
const int Example::BufSize; // definition
Related
I want to declare an array inside a structure with a predefined constant size, but it gives me this error : expected a ']'.
#define MAX_SZAMJEGY 200;
struct szam {
int szj[MAX_SZAMJEGY];
bool negative;
};
Macro expands to
int szj[200;];
which is not valid C++ code.
remove ; from #define MAX_SZAMJEGY 200;
A preferred C++ solution is to use constants rather than macros. This way you will not have a semicolon problem, and it comes with tons of other benefits as well. Here is how:
(C++ 98):
static const size_t MAX_SZAMJEGY 200;
struct szam {
int szj[MAX_SZAMJEGY];
bool negative;
};
(C++11)
static constexpr size_t MAX_SZAMJEGY=200;
struct szam {
int szj[MAX_SZAMJEGY];
bool negative;
};
And while you are on it, and if you are using C++11, you might as well replace C-style array with C++ std::array. While it doesn't make too much of a difference, it is slightly more convenient to use.
try
#define MAX_SZAMJEGY 200
instead of
#define MAX_SZAMJEGY 200;
(the semicolon enters the macro)
This code will not compile:
#ifndef RemoteControl_h
#define RemoteControl_h
#include "Arduino.h"
class RemoteControl
{
public:
RemoteControl();
~RemoteControl();
static void prev_track();
static void next_track();
static void play_pause_track();
static void mute();
static void vol_up();
static void vol_down();
void respond(int code);
void add_code(int code, void (*func)());
private:
boolean active = true;
struct pair {
int _code;
void (*_func)();
};
const int max = 1000;
int database_length = 0;
pair database[max]; //This line doesn't compile unless I use a literal constant instead of "max"
};
#endif
But if I put the section below in the constructor for the class instead it works fine.
const int max = 1000;
int database_length = 0;
pair database[max];
Am I not allowed to declare an array within a class in c++ and use a virtual constant as the length? I am working in arduino if that makes a difference, but I expect that I am not understanding something with the c++ language since this is a standard .h file. Oh and the problem isn't the .cpp file because I completely removed it with the same results: compiles with literal constant length but not virtual constant length.
In C or C++,try using malloc() in stdlib.h, cstdlib for c++. Don't forget free()
const int max = 1000;
struct pair *ptr = malloc(sizeof(pair) * max); // allocated 1000 pairs
free(ptr); // when the amount of memory is not needed anymore
Let me first clear a few things up for you.
In C, a const variable is considered as const-qualified, it is not a compile-time constant value (unlike an integer literal, which is a compile time constant value). So, as per the rules for normal array size specification, you cannot even use a const variable in this case.
In C, we may have the provision to use VLA which enables us to use syntax like pair database[max] even if max is not a const variable but that is again some optional feature of the compiler (as per C11).
In C++, we can use a const variable as the size of array, as in C++, a const variable is a compile time constant.
So, to answer your question:
In C, your code will be ok if your compiler supports VLA. and even if max is not const.
In C++, there is no VLA, but it maybe supported as a gnu extension. If max is const, it will be ok.
The easiest fix is to just take the
const int max = 1000;
out of the class and put it above the class.
Even better would be to ensure that it is a compile-time constant like so:
constexpr int max = 1000;
I'm building a toy interpreter and I have implemented a token class which holds the token type and value.
The token type is usually an integer, but how should I abstract the int's?
What would be the better idea:
// #defines
#define T_NEWLINE 1
#define T_STRING 2
#define T_BLAH 3
/**
* Or...
*/
// enum
enum TokenTypes
{
t_newline = 1,
t_string = 2,
t_blah = 3
};
Enums can be cast to ints; furthermore, they're the preferred way of enumerating lists of predefined values in C++. Unlike #defines, they can be put in namespaces, classes, etc.
Additionally, if you need the first index to start with 1, you can use:
enum TokenTypes
{
t_newline = 1,
t_string,
t_blah
};
Enums work in debuggers (e.g. saying "print x" will print the "English" value). #defines don't (i.e. you're left with the numeric and have to refer to the source to do the mapping yourself).
Therefore, use enums.
There are various solutions here.
The first, using #define refers to the old days of C. It's usually considered bad practice in C++ because symbols defined this way don't obey scope rules and are replaced by the preprocessor which does not perform any kind of syntax check... leading to hard to understand errors.
The other solutions are about creating global constants. The net benefit is that instead of being interpreted by the preprocessor they will be interpreted by the compiler, and thus obey syntax checks and scope rules.
There are many ways to create global constants:
// ints
const int T_NEWLINE = 1;
struct Tokens { static const int T_FOO = 2; };
// enums
enum { T_BAR = 3; }; // anonymous enum
enum Token { T_BLAH = 4; }; // named enum
// Strong Typing
BOOST_STRONG_TYPEDEF(int, Token);
const Token NewLine = 1;
const Token Foo = 2;
// Other Strong Typing
class Token
{
public:
static const Token NewLine; // defined to Token("NewLine")
static const Token Foo; // defined to Token("Foo")
bool operator<(Token rhs) const { return mValue < rhs.mValue; }
bool operator==(Token rhs) const { return mValue == rhs.mValue; }
bool operator!=(Token rhs) const { return mValue != rhs.mValue; }
friend std::string toString(Token t) { return t.mValue; } // for printing
private:
explicit Token(const char* value);
const char* mValue;
};
All have their strengths and weaknesses.
int lacks from type safety, you can easily use one category of constants in the place where another is expected
enum support auto incrementing but you don't have pretty printing and it's still not so type safe (even though a bit better).
StrongTypedef I prefer to enum. You can get back to int.
Creating your own class is the best option, here you get pretty printing for your messages for example, but that's also a bit more work (not much, but still).
Also, the int and enum approach are likely to generate a code as efficient as the #define approach: compilers substitute the const values for their actual values whenever possible.
In the cases like the one you've described I prefer using enum, since they are much easier to maintain. Especially, if the numerical representation doesn't have any specific meaning.
Enum is type safe, easier to read, easier to debug and well supported by intellisense. I will say use Enum whenever possible, and resort to #define when you have to.
See this related discussion on const versus define in C/C++ and my answer to this post also list when you have to use #define preprocessor.
Shall I prefer constants over defines?
I vote for enum
#define 's aren't type safe and can be redefined if you aren't careful.
Another reason for enums: They are scoped, so if the label t_blah is present in another namespace (e.g. another class), it doesn't interfere with t_blah in your current namespace (or class), even if they have different int representations.
enum provided type-safety and readability and debugger. They are very important, as already mentioned.
Another thing that enum provides is a collection of possibilities. E.g.
enum color
{
red,
green,
blue,
unknown
};
I think this is not possible with #define (or const's for that matter)
Ok, many many answers have been posted already so I'll come up with something a little bit different: C++0x strongly typed enumerators :)
enum class Color /* Note the "class" */
{
Red,
Blue,
Yellow
};
Characteristics, advantages and differences from the old enums
Type-safe: int color = Color::Red; will be a compile-time error. You would have to use Color color or cast Red to int.
Change the underlying type: You can change its underlying type (many compilers offer extensions to do this in C++98 too): enum class Color : unsigned short. unsigned short will be the type.
Explicit scoping (my favorite): in the example above Red will be undefined; you must use Color::Red. Imagine the new enums as being sort of namespaces too, so they don't pollute your current namespace with what is probably going to be a common name ("red", "valid", "invalid",e tc).
Forward declaration: enum class Color; tells the compiler that Color is an enum and you can start using it (but not values, of course); sort of like class Test; and then use Test *.
I'm wondering what the difference is between using a static const and an enum hack when using template metaprogramming techniques.
EX: (Fibonacci via TMP)
template< int n > struct TMPFib {
static const int val =
TMPFib< n-1 >::val + TMPFib< n-2 >::val;
};
template<> struct TMPFib< 1 > {
static const int val = 1;
};
template<> struct TMPFib< 0 > {
static const int val = 0;
};
vs.
template< int n > struct TMPFib {
enum {
val = TMPFib< n-1 >::val + TMPFib< n-2 >::val
};
};
template<> struct TMPFib< 1 > {
enum { val = 1 };
};
template<> struct TMPFib< 0 > {
enum { val = 0 };
};
Why use one over the other? I've read that the enum hack was used before static const was supported inside classes, but why use it now?
Enums aren't lvals, static member values are and if passed by reference the template will be instanciated:
void f(const int&);
f(TMPFib<1>::value);
If you want to do pure compile time calculations etc. this is an undesired side-effect.
The main historic difference is that enums also work for compilers where in-class-initialization of member values is not supported, this should be fixed in most compilers now.
There may also be differences in compilation speed between enum and static consts.
There are some details in the boost coding guidelines and an older thread in the boost archives regarding the subject.
For some the former one may seem less of a hack, and more natural. Also it has memory allocated for itself if you use the class, so you can for example take the address of val.
The latter is better supported by some older compilers.
On the flip side to #Georg's answer, when a structure that contains a static const variable is defined in a specialized template, it needs to be declared in source so the linker can find it and actually give it an address to be referenced by. This may unnecessarily(depending on desired effects) cause inelegant code, especially if you're trying to create a header only library. You could solve it by converting the values to functions that return the value, which could open up the templates to run-time info as well.
"enum hack" is a more constrained and close-enough to #define and that helps to initialise the enum once and it's not legal to take the address of an enum anywhere in the program and it's typically not legal to take the address of a #define, either. If you don't want to let people get a pointer or reference to one of your integral constants, an enum is a good way to enforce that constraint. To see how to implies to TMP is that during recursion, each instance will have its own copy of the enum { val = 1 } during recursion and each of those val will have proper place in it's loop. As #Kornel Kisielewicz mentioned "enum hack" also supported by older compilers those forbid the in-class specification of initial values to those static const.
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
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
How about enums?
constants.hpp
enum {
BEGINNING_HEALTH = 10,
BEGINNING_MANA = 5
}
Use "static const int" in your .hpp file, and put nothing in the .cpp file (except whatever other code you have there of course).
make use of namespaces:
namespace GameBeginning {
const int HEALTH = 10;
const int MANA = 5;
};
then u can use as player.health = GameBeginning::HEALTH;
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?
What ever happened to a simple:
#define BEGINNING_HEALTH 10
Man, those were the days.
Oh wait, those still are the days!
perhaps something along the lines of a static class?
class CONSTANTS {
public:
static inline int getMana() { return 10;};
};
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".