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

C++C

C++ Problem Overview


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.

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

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.

Solution 5 - C++

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.

Solution 6 - C++

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).

Solution 7 - C++

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?)

Solution 8 - C++

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.

Solution 9 - C++

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).

Solution 10 - C++

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.

Solution 11 - C++

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".

Solution 12 - 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.

Solution 13 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZach RattnerView Question on Stackoverflow
Solution 1 - C++David Rodríguez - dribeasView Answer on Stackoverflow
Solution 2 - C++Alok SaveView Answer on Stackoverflow
Solution 3 - C++iammilindView Answer on Stackoverflow
Solution 4 - C++Mike SeymourView Answer on Stackoverflow
Solution 5 - C++BЈовићView Answer on Stackoverflow
Solution 6 - C++mondaugenView Answer on Stackoverflow
Solution 7 - C++Swift - Friday PieView Answer on Stackoverflow
Solution 8 - C++SeanRameyView Answer on Stackoverflow
Solution 9 - C++TimView Answer on Stackoverflow
Solution 10 - C++Zach RattnerView Answer on Stackoverflow
Solution 11 - C++angstyloopView Answer on Stackoverflow
Solution 12 - C++BenjaminBView Answer on Stackoverflow
Solution 13 - C++didiView Answer on Stackoverflow