Automating the generation of an enum lookup table - c++

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.

Related

Why doesn't the vscode-cpptools extension provide intellisense for namespaced declarations inside macro definitions?

I am using VS Code. All the following description happens on VS Code env.
I got one header with namespace "Loki" defined which is called "Typelist.h"
I am trying to use a struct inside this namespace defined in this header.
I did:
# define LOKI_TYPELIST_1(T1) ::Loki::TypeList<T1, ::Loki::NullType>
# define LOKI_TYPELIST_2(T1, T2) ::Loki::TypeList<T1, LOKI_TYPELIST_1(T2)>
Normally, I think it should give me intellisense when I am trying to type ::Loki::[Something from namespace Loki], but it doesn't show me anything.
Even, when I am trying to use LOKI_TYPELIST_1 when I define LOKI_TYPELIST_2, it doesn't work either.
What's going on here? Why doesn't the vscode-cpptools extension provide intellisense for namespaced declarations inside macro definitions?
P.S. I did include "Typelist.h" in my current header.
As far as I know, the vscode-cpptools doesn't provide intellisense inside macro definitions.
This is actually fairly reasonable. What a macro definition really means when the macro gets used is often highly dependent on context where it is used. After all... isn't one of the main features of macros?
Take for an (unrealistic, toy) example: #define FOO std::. Let's say I expect to see identifiers for things declared inside the global std namespace when I trigger VS Code to provide suggestions there. Who's to say some lunatic won't redefine what std is and then use FOO?
Granted, if it were instead #define FOO ::std::, our imaginary lunatic is out of luck, but I'd wager this is a case of "It's too much work to distinguish between what is guaranteeable as known inside a macro body, so let's just not provide intellisense there."
Here's more (and probably better) food for thought: How would intellisense know what is declared inside the std namespace at the point of the macro usage? That would depend on what standard headers have been included and what forward declarations have been made before the point of the macro usage. At one usage site, I might have included <string>, and at another, not have included it. Etc. A macro can be used in multiple places. How do you give intellisense for something that can have different valid suggestions depending on where it is used?
Even with such a small example (and there are many varying others), there are already two challenges that make this unduly difficult for the vscode-cpptools extension to provide good suggestions/autocomplete for.
Granted- the vscode-cpptools extension can and will show problem highlighting at/inside the macro if any usage of that macro has problems, because it uses compiler diagnostic messages to find the "site" of the problem, and most compilers will report the specific macro line and column where the problem is happening in their diagnostic messages (in addition to the line and column of where the macro is being used).

C++ best way to switch between configs

I have some code that I need to run for separate cases. I would have to switch mostly some enums and statics for those cases. So, let's say I have enums
enum class City { NY, LA, W_DC, ... }
City capital = City::W_DC
and for the other case
enum class City { LDN, BMH, EDB, ... }
City capital = City::LDN
Assuming I have a lot of those enums, what is the best way to reuse most of the code and switch between those configuration. To be clear, this is not meant to happen during runtime, the program is supposed to compile for one case and be oblivious about anything else.
EDIT: following StackOverflowUser to use macros
would it be a good approach to store the different enum configs in different namespaces and then do
#IFDEF USE_NAMESPACE_A
using namespace namespace_a
#ELSE
using namespace namespace_a
#ENDIF
Creating macros and using #ifdef MACRONAME is the best way to check things before run time, in my opinion.
You can also create constexpr variables and use ifs to evaluate those variables' values. Since the variables are constexpr, the compiler would most likely optimize them away.
One option is to create separate source files, each containing the enum you want. You then make different compile targets that compile the relevant file as part of the build.
Another option is to use the #ifdef...#else preprocessor macros as stated previously, but you'll likely have different compile targets to define the macro that includes the correct file. Rather than set it up so you have to change code AND change the build, just put it in the build.
But, honestly, enums are probably not the best way to do what you're wanting to do. A lookup from a file/database/or some other datasource at runtime would likely be a more maintainable approach. It requires a bit more work obviously, but if this is something to maintain long-term you'll thank yourself later.

In C/C++, is there a directive similar to #ifndef for typedefs?

If I want to define a value only if it is not defined, I do something like this :
#ifndef THING
#define THING OTHER_THING
#endif
What if THING is a typedef'd identifier, and not defined? I would like to do something like this:
#ifntypedef thing_type
typedef uint32_t thing_type
#endif
The issue arose because I wanted to check to see if an external library has already defined the boolean type, but I'd be open to hearing a more general solution.
There is no such thing in the language, nor is it needed. Within a single project you should not have the same typedef alias referring to different types ever, as that is a violation of the ODR, and if you are going to create the same alias for the same type then just do it. The language allows you to perform the same typedef as many times as you wish and will usually catch that particular ODR (within the same translation unit):
typedef int myint;
typedef int myint; // OK: myint is still an alias to int
//typedef double myint; // Error: myint already defined as alias to int
If what you are intending to do is implementing a piece of functionality for different types by using a typedef to determine which to use, then you should be looking at templates rather than typedefs.
C++ does not provide any mechanism for code to test presence of typedef, the best you can have is something like this:
#ifndef THING_TYPE_DEFINED
#define THING_TYPE_DEFINED
typedef uint32_t thing_type
#endif
EDIT:
As #David, is correct in his comment, this answers the how? part but importantly misses the why? It can be done in the way above, If you want to do it et all, but important it you probably don't need to do it anyways, #David's answer & comment explains the details, and I think that answers the question correctly.
No there is no such facility in C++ at preprocessing stage. At the max can do is
#ifndef thing_type
#define thing_type uint32_t
#endif
Though this is not a good coding practice and I don't suggest it.
Preprocessor directives (like #define) are crude text replacement tools, which know nothing about the programming language, so they can't act on any language-level definitions.
There are two approaches to making sure a type is only defined once:
Structure the code so that each definition has its place, and there's no need for multiple definitions
#define a preprocessor macro alongside the type, and use #ifndef to check for the macro definition before defining the type.
The first option will generally lead to more maintainable code. The second could cause subtle bugs, if you accidentally end up with different definitions of the type within one program.
As other have already said, there are no such thing, but if you try to create an alias to different type, you'll get a compilation error :
typedef int myInt;
typedef int myInt; // ok, same alias
typedef float myInt; // error
However, there is a thing called ctag for finding where a typedef is defined.
The problem is actually real PITA, because some APIs or SDKs redefine commonly used things. I had issue that header files for a map processing software (GIS) were redefining TRUE and FALSE (generally used by windows SDK)keywords to integer literals instead of true and false keywords ( obviously, that can break SOMETHING). And yes, famous joke "#define true false" is relevant.
define would never feel a typedef or constant declared in C\C++ code because preprocessor doesn't analyze code, it only scans for # statements. And it modifies code prior to giving it to syntax analyzer. SO, in general, it's not possible.
https://msdn.microsoft.com/en-us/library/5xkf423c.aspx?f=255&MSPPError=-2147217396
That one isn't portable so far, though there were known request to implement it in GCC. I think, it also counts as "extension" in MSVC. It's a compiler statement, not a preprocessor statement, so it will not "feel" defined macros, it would detect only typedefs outside of function body. "full type" there means that it will react on full definition, ignoring statements like "class SomeClass;". Use it at own risk.
Edit: apparently it also supported on MacOS now and by Intel comiler with -fms-dialect flag (AIX\Linux?)
This might not directly answer the question, but serve as a possible solution to your problem.
Why not try something like this?
#define DEFAULT_TYPE int // just for argument's sake
#ifndef MY_COOL_TYPE
#define MY_COOL_TYPE DEFAULT_TYPE
#endif
typedef MY_COOL_TYPE My_Cool_Datatype_t;
Then if you want to customize the type, you can either define MY_COOL_TYPE somewhere above this (like in a "configure" header that is included at the top of this header) or pass it as a command line argument when compiling (as far as I know you can do this with GCC and LLVM, maybe others, too).
No there is nothing like what you wanted. I have had your same problem with libraries that include their owntypedefs for things like bool. It gets to be a problem when they just don't care about what you use for bool or if any other libs might be doing the same thing!!
So here's what I do. I edit the header file for the libs that do such things and find the typedef bool and add some code like this:
#ifdef USE_LIBNAME_BOOL
typedef unsigned char bool; // This is the lib's bool implementation
#else
#include <stdbool.h>
#endif
Notice that I included if I didn't want to use the libs' own bool typdef. This means that you need C99 support or later.
As mentioned before this is not included in the C++ standard, but you might be able to use autotools to get the same functionality.
You could use the ac_cxx_bool macro to make sure bool is defined (or different routines for different datatypes).
The solution I ended up using was including stdbool.h. I know this doesn't solve the question of how to check if a typedef is already defined, but it does let me ensure that the boolean type is defined.
This is a good question. C and Unix have a history together, and there are a lot of Unix C typedefs not available on a non-POSIX platform such as Windows (shhh Cygwin people). You'll need to decide how to answer this question whenever you're trying to write C that's portable between these systems (shhhhh Cygwin people).
If cross-platform portability is what you need this for, then knowing the platform-specific preprocessor macro for the compilation target is sometimes helpful. E.g. windows has the _WIN32 preprocessor macro defined - it's 1 whenever the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. But it's presence also informs us that we're on a Windows machine. This means that e.g. ssize_t won't be available (ssize_t, not size_t). So you might want to do something like:
#ifdef _WIN32
typedef long ssize_t;
#endif
By the way, people in this thread have commented about a similar pattern that is formally called a guard. You see it in header files (i.e. interfaces or ".h" files) a lot to prevent multiple inclusion. You'll hear about header guards.
/// #file poop.h
#ifndef POOP_H
#define POOP_H
void* poop(Poop* arg);
#endif
Now I can include the header file in the implementation file poop.c and some other file like main.c, and I know they will always compile successfully and without multiple inclusion, whether they are compiled together or individually, thanks to the header guards.
Salty seadogs write their header guards programmatically or with C++11 function-like macros. If you like books I recommend Jens Gustedt's "Modern C".
It is not transparent but you can try to compile it one time without typedef (just using the alias), and see if it compiles or not.
There is not such things.
It is possible to desactivate this duplicate_typedef compilator error.
"typedef name has already been declared (with same type)"
On a another hand, for some standardized typedef definition there is often a preprocessor macro defined like __bool_true_false_are_defined for bool that can be used.

Pointless 'MIDL_INTERFACE' Macro in winapi?

After browsing some old code, I noticed that some classes are defined in this manner:
MIDL_INTERFACE("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
Classname: public IUnknown {
/* classmembers ... */
};
However, the macro MIDL_INTERFACE is defined as:
#define MIDL_INTERFACE(x) struct
in C:/MinGW/include/rpcndr.h (somewhere around line 17). The macro itself is rather obviously entirely pointless, so what's the true purpose of this macro?
In the Windows SDK version that macro expands to
struct __declspec(uuid(x)) __declspec(novtable)
The first one allows use of the __uuidof keyword which is a nice way to get the guid of an interface from the typename. The second one suppresses the generation of the v-table, one that is never used for an interface. A space optimization.
This is because MinGW does not support COM (or rather, supports it extremely poorly). MIDL_INTERFACE is used when defining a COM component, and it is generated by the IDL compiler, which generates COM type libraries and class definitions for you.
On MSVC, this macro typically expands to more complicated initialization and annotations to expose the given C++ class to COM.
If I had to guess, it's for one of two use cases:
It's possible that there's an external tool that parses the files looking for declarations like these. The idea is that by having the macro evaluate to something harmless, the code itself compiles just fine, but the external tool can still look at the source code and extract information out of it.
Another option might be that the code uses something like the X Macro Trick to selectively redefine what this preprocessor directive means so that some other piece of the code can interpret the data in some other way. Depending on where the #define is this may or may not be possible, but it seems reasonable that this might be the use case. This is essentially a special-case of the first option.

Remove dependancy constants from enum definition

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.