I am trying to safely remove a dependency from my project by using opaque structures and forward declarations but like most I am still stuck on my enums.
The header file dependency I am trying to remove from my header files has defined constants that I want to set my enumeration's values to. Something like this
// depends header
#define DEP_TYPE_ONE 1
#define DEP_TYPE_TWO 2
#define DEP_TYPE_THREE 3
// My header
enum TYPES
{
T_ONE = DEP_TYPE_ONE,
T_TWO = DEP_TYPE_TWO,
T_THREE = DEP_TYPE_THREE
}
I am trying to figure out a way to not have to include the depends header in my header.
Odds are the answer is probably simply 'you can't do that' but I just want to ask because a solution would make my life infinity easier.
How about removing the include of the depends header, hard code the values, and comment the dependency:
// my_header.h
// NOTE: Enumerands must be in sync with symbols defined in depends.h
enum TYPES
{
T_ONE = 1, // DEP_TYPE_ONE
T_TWO = 2, // DEP_TYPE_TWO
T_THREE = 3 // DEP_TYPE_THREE
};
To allay fears about the values getting out of sync, you can have another header or source file (one that users of your class or API don't get) that contains one or more compile-time asserts:
// Some non-distributed file
#include <depends.h>
#include "my_header.h"
// Compile-time assertion macro
#define compile_time_assert(cond, msg) \
typedef char msg[(cond) ? 1 : -1]
// Check assumptions at compile time...
compile_time_assert(T_ONE==DEP_TYPE_ONE, ValueOutOfSync1);
compile_time_assert(T_TWO==DEP_TYPE_TWO, ValueOutOfSync2);
.
.
.
This would give you a compile time error if the values ever get out of sync.
For more info on the compile_time_assert macro, see: http://www.embedded.com/columns/programmingpointers/164900888?_requestid=379501
It is not what you want, but it is the only way not to include the depends header in your header:
enum TYPES
{
T_ONE = 1,
T_TWO = 2,
T_THREE = 3
}
Not a perfect answer, but have you considered anonymous enums? I had a similar problem once when using a charting library that defined a lot of constants in a header with a lot of internal dependency. This was affecting our compile-time. So, i just MOCked the entire #define's into an anonymous enumeration in an anonymous namespace in a header! Something like :-
namespace {
enum {
DEP_TYPE_ONE = 1,
DEP_TYPE_TWO,
// ....
DEP_TYPE_LAST
};
}
With this approach you will not have to refactor a lot of code that directly uses those named constants. But it is a maintainance nightmare to update the enum as soon as the header defines new constants.
Well worth a try in your case i guess.
HTH,
You are right, you can't. You are dealing with the pre-processor here not the compiler (as with the forward declarations).
It may be possible to 'fake it' if your compiler supports an "forced include" option, but the dependency still remains, and you still need the file to build.
Related
Throughout a C++ codebase I'm working in, the pattern for declaring constants looks something like this.
// module_constants.h
#ifndef MODULE_CONSTANTS
#define MODULE_CONSTANTS
namespace module {
extern const int SOME_CONST;
}
#endif
// module_constants.cpp
#include "module_constants.h"
namespace module {
const int SOME_CONST = 1;
}
What are the merits of this approach rather than defining all of the constant values in the header?
The single advantage I know of is that you only have to recompile a single cpp-file when you change the constant’s value and not every file that directly or indirectly includes the header file.
That can be particularly useful when you provide a dynamically linked library and want to patch it without recompiling the actual application.
Some drawbacks are that
(as latedeveloper wrote) you can't use them at places where a constant expression is required (e.g. array bounds or template parameters) outside of the cppfile, in which you defined it.
you make the optimizer's life harder.
from a tooling perspective e.g. intellisense won't show you it's value.
Well, by putting it in the header you'd run into the one-definition rule if you include it in more than one cpp file.
But, on the other hand, you can create it as a constexpr in the header I believe.
I'm using a technique similar to this to associated information and/or actions with enumerators. It works pretty well, but there's a minor issue of needing to effectively list every constant twice, once in the header file in the enum declaration, and once in the source file in the lookup table. I'm wondering if there's any good way, probably with preprocessor trickery (Boost.Preprocessor is acceptable), to "automate" it so that I can enter the enum constants and associated values etc in just one place and have all the necessary stuff (perhaps even the lookup struct itself) get generated.
I'd prefer a method that maintains vaguely enum-style syntax, if possible; eg, something like DECLARE_ENUM(...) {E_CONST(...), E_CONST(...)};. I've seen some sites mentioning the idea of double-including the header file in order to achieve this, i.e. something like this:
#include "my_enum.hpp"
#undef ENUM_HPP // undefine the include guard
#undef E_CONST
#define E_CONST(...) /* something here */
#include "my_enum.hpp"
...but I'm not sure how useful that technique would be here. In particular, there is more than just the enum defined in the header; the lookup table struct is also there, along with a couple of other related enums and supporting functions.
I'm already using a macro to define the elements in the lookup table (it uses C99 initializers so that the entries will always be in the right place even if I rearrange the order of the enum constants).
A solution that can be applied to multiple enums would be nice as well.
I'm using clang (Apple-3.1) for this and am not particularly worried about portability.
I had an attempt somewhere that I threw away... I can't remember why it didn't work. Maybe I can find it in Time Machine...
Using the preprocessor trick, you would define your enums in a different file (say, enum_foo.def). It would be an unguarded file that gets #included.
ENUM_FOO_DEF(ALPHA, 9, 2)
ENUM_FOO_DEF(BETA, 10, 3)
ENUM_FOO_DEF(GAMMA, 12, 7)
ENUM_FOO_DEF(DELTA, 13, 11)
//...
Then in your source file, you would do something along the lines of:
enum FooEnum {
#define ENUM_FOO_DEF(X,Y,Z) FOO_E_ ## X,
#include "enum_foo.def"
#undef ENUM_FOO_DEF
FOO_E_MAX
};
And you can do something similar to populate your table of enum attributes.
Look at my gist for string enums https://gist.github.com/3058317
Maybe you should write your own code generator which takes some data file with the names and associated values and generates the header file and data table, probably as a standalone C module.
This program will be trivial to write, but immensely powerful for your use.
Being pretty new to C++, I don't quite understand some instructions I encounter such as:
#ifndef BOT_H_
#define BOT_H_
#include "State.h"
/*
This struct represents your bot in the game of Ants
*/
struct Bot
{
State state;
Bot();
void playGame(); //plays a single game of Ants
void makeMoves(); //makes moves for a single turn
void endTurn(); //indicates to the engine that it has made its moves
};
#endif //BOT_H_
What I don't understand is the "#ifndef BOT_H_" and the "#define -- #endif"
From what I gather, it defines a constant BOT_H_ if it's not already defined when the precompiler looks at it. I don't actually get how the struct inside it is a constant and how it is going to let me access the functions inside it.
I also don't see why we're doing it this way? I used C++ a while back and I wasn't using .h files, so it might be something easy I'm missing.
This is known as an include guard, to prevent the contents of a header file from being #included more than once.
That is, it prevents the contents of the header file from being copied into the file that #includes it when it has already #included it before.
The #define isn't defining a constant for the struct, but it's simply defining a constant with no value. If that constant was previously defined, the struct will not be redeclared.
It's called "include guard". It protects you from redefinitions occuring when a header is included more than once. There's also non-standard #pragma once that does the same thing, but might not be supported everywhere.
It does not define a constant whose value is the struct. It defines a constant with an empty value.
It's there so that the content of the header is not included twice. Basically it says something like:
if (!bot_h_included)
{
bot_h_included = true;
// code from the header
}
this is called a header guard it stops the compiler compiling or including the code more than once it is similar to pragma once
Just a side note, I don't recommend using #pragma once I see it a lot in a MVC compatible compilers but just a couple of weeks ago I was working with HP UX and the HP-CC does not support #pragma once, I strongly recommend using #ifndef/#define combinations.
I am wondering why C++ compilers don't generate header guards automatically for headers?
// Why do I have to write this for every .hpp file I create?!!
#ifndef myheader_hpp__
#define myheader_hpp__
// ...
#endif
I haven't met a situation where they aren't needed when I write my headers. I can't see a real use-case of the opposite behavior, but I would be glad to see one. Is there a technical difficulty or is it just history?!
There are some preprocessor tricks that require the same header included multiple times into the same compilation unit. Another reference.
Besides that, most compilers do allow you to shorten all of that down to:
#pragma once
To a compiler, automatically putting in include guards isn't truly practical. You can define prototypes for methods/functions/classes/etc without running into problems, and this is usually done in a header. When a class is defined in a header, though, you run into the problem of having the class defined more than once by the compiler if it is included by two different .cpp files or other headers.
Really, include guards are just one trick for headers. You don't always need them, and there are some cases where you wouldn't use them. This is actually easier, believe it or not.
Because it's a general purpose mechanism to insert one file into another.
It's just that general purpose ability is used for a very common specific purpose in 99% of the cases.
I'll simply point you to the Clang / LLVM project.
In this project, they created a way to encode data using a simple descriptive language, that is then fed up to a tool (called tblgen for Table Generator) that is meant to produce a C++ file. For example, the diagnostics:
let Component = "Sema" in {
let CategoryName = "Semantic Issue" in {
// Constant expressions
def err_expr_not_ice : Error<
"expression is not an integer constant expression">;
....
There are a few thousands diagnostics in Clang, separated in several files. Once processed by tblgen, they will generate a huge .inc file which, for each diagnostic, will contain a macro call. By defining the macro and including the file, you can produce a C++ table (or anything else really, but the use is generally for tables):
static const StaticDiagInfoRec StaticDiagInfo[] = {
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \
SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER, \
CATEGORY,BRIEF,FULL) \
{ diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, \
NOWERROR, SHOWINSYSHEADER, CATEGORY, \
STR_SIZE(#ENUM, uint8_t), STR_SIZE(GROUP, uint8_t), \
STR_SIZE(DESC, uint16_t), STR_SIZE(BRIEF, uint16_t), \
STR_SIZE(FULL, uint16_t), \
#ENUM, GROUP, DESC, BRIEF, FULL },
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
#include "clang/Basic/DiagnosticLexKinds.inc"
#include "clang/Basic/DiagnosticParseKinds.inc"
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#undef DIAG
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
And the same files can produce different tables, since you are free to write the macros as you wish.
It is, of course, a very specific use.
But don't worry, even though the modules didn't make it into C++11, we can hope for C++1x.
Sample.h
namespace Testing
{
enum Type
{
DATA = 0,
MORE_DATA
};
}
Now in Sample2.h, using the same namespace, can I access the DataType defined in Sample.h, without including it?
namespace Testing
{
Type test;
}
The question has come up, because I have files that implement this, and seem to build with no problem.
Another user is trying to build, but reports that he has to #include "Sample.h" in Sample2.h in order to build.
Most likely the files build because some earlier include file is including Sample.h for you. When the earlier include file is omitted (or moved after Sample2.h) the files will no longer compile.
Forward enum declarations are not supported in most current compilers. It is a planned feature of up coming C++0x. You can create pointers to Type probably, but cannot instantiate, this is compatible with other types (structs and classes) as well.
Ow, my bad, I saw it wrong i guess. Anyway, read the others and read this as well. Headers are not compiled stand alone. Therefore, if you don't include a required heading in your header and included that in the cpp file you will not run into any errors. As long as all the cpp files contain both headers with the required order there will be no problems at all. However, this is not a good idea, it is best to include any necessary files within your header and use header guards to ensure they are not added twice. I hope this makes sense.
Yes, you will need to include Sample.h within Sample2.h. The definition of Type is not visible to the compiler within Sample2.h simply because the namespace name is the same within the 2 files.
The only thing you gain by having the same namespace names in the 2 files is that Type does not need to have its namespace stated explicitly in Sample2.h. For instance, if the 2 namespaces were not the same:
Sample.h
namespace Testing
{
enum Type
{
DATA = 0,
MORE_DATA
};
}
Sample2.h
#include "Sample.h"
namespace Testing1
{
Testing::Type test;
}