views:

60

answers:

4

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.

A: 

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 
} 
Kirill V. Lyadvinsky
tbh I am pretty much guaranteed that those values will never ever change, but I would feel really insecure while writing that all the same
Charles
A: 

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,

Abhay
That is an interesting idea. Its really just one step shy of adding the dependency header into my project headers distributable but has the benefit of not doing that :p
Charles
A: 

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.

Clifford
+1  A: 

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

Scott Smith
A compile time assert! What a great idea!
Charles