4

NOTE: This is NOT a duplicate of the question linked by Paul T, because I am asking if it is possible to determine if a type is of a certain broader incomplete type/kind at compile time, not if a symbol has been registered at compile time. This seems like a fundamental misunderstanding of the question.

I am writing a library in C that deals with pseudo-generic functions which take a type as an argument through a macro wrapper.

To spare the details (because they are rather complicated) there are two possible features that could help, I think:

  • Being able to detect if a type is a pointer at compile time. (No, the "use _Generic to test if you get ptrdiff_t from subtraction" trick won't work, because structures are a possibility, and you can't subtract structures.)

  • Being able to detect if a type is a struct at compile time. (If this was possible, then the aforementioned _Generic trick could be used if the type was detected as not being a struct.)

I've tried everything I could think of on Godbolt (even trying to compare types to incomplete anonymous structs and toying with __builtin_types_compatible_p) and wasn't able to find any solutions.

If anyone has any solutions I'd love to see them, otherwise I may just end up having to complicate the design a bit-- so not the end of the world if it's impossible, but it would be ideal if it can be done.

To give a basic idea of what one of these macros might look like or their expected output:

int *a; assert(!IS_STRUCT(a)); assert(IS_POINTER(a)); struct {} b; assert(IS_STRUCT(b)); assert(!IS_POINTER(b)); 

shouldn't throw any errors.

13
  • Would (void) &((object_of_unknown_type)[0]); meet your goal "to detect if a type is a pointer"? Commented Jan 31, 2019 at 2:48
  • @PaulT. That's not at all the same thing though. That's checking if a type is defined at compile time, mine is querying if a type is of a certain kind at compile time. Commented Jan 31, 2019 at 2:51
  • @chux I don't see what that's supposed to do? I can certainly just dereference to get a compile-time error if a type isn't a pointer, but as the post demonstrated with the macro examples, I want to actually be able to get this as a static result-- perhaps my use of assert for the example was misleading, in which case I apologize. Commented Jan 31, 2019 at 2:53
  • 1
    @chux Correct. Ideally that IS_STRUCT() result would also be a constant expression. Commented Jan 31, 2019 at 3:09
  • 1
    Certainly #define IS_STRUCT_SUBSTANTIAL(x) (sizeof(x) > sizeof(void*)), when true, x must be a struct and not an object pointer. Of course, when false, x could be a pointer or a wee struct. Likely not generic enough, but a step. Knowing how this is used in the larger picture may help. Commented Jan 31, 2019 at 4:12

2 Answers 2

4

Complete Answer (if EDG Front End used):

If your IDE / compiler is using the EDG C++ Front End (which a lot are), and you are using C, not C++ (which your tag suggests), and you say you ARE using typeof, then you can detect a structs as follows (see the latest manual, page 75):

/* Test if EDG Front End is used*/ #if defined(__EDG__) && defined(__EDG_VERSION__) #define IS_STRUCT(expression_or_type_name) __is_class(typeof (expression_or_type_name))) #endif 

since in C __is_class() will only be true for a struct (http://www.cplusplus.com/reference/type_traits/is_class/).

Further, pointers can similarly be detected as follows:

/* Test if EDG Front End is used*/ #if defined(__EDG__) && defined(__EDG_VERSION__) #define IS_POINTER(expression_or_type_name) (__is_convertible_to(typeof (expression_or_type_name), void*) || __is_convertible_to(typeof (expression_or_type_name), void const*) || __is_convertible_to(typeof (expression_or_type_name), void volatile*) || __is_convertible_to(typeof (expression_or_type_name), void const volatile*)) #endif 

(http://www.cplusplus.com/reference/type_traits/is_convertible/)

Sign up to request clarification or add additional context in comments.

Comments

0
  1. It’s not possible in standard C. Whatever solutions there may be must be implementation-defined.

  2. It seems that C is not a suitable language for your problem domain. Short of esoteric platforms that come without C++ support, there seems to be little reason to have to solve this in C. On most any platform where C is available, so is C++. Since you claim that you use gcc, then C++ is surely available and you can process some of the input using a C++ compiler. You could do the input processing as a generator step: run the code through a C++ compiler to generate source code that defines constants that capture type properties sought.

1 Comment

1. Fair, though realistically I don't think many people use compilers outside of gcc/msvc/clang, so raw standard C compliance isn't really a concern. 2. Again fair, but I would prefer to use C. C++ brings other baggage with it and leaves behind some things, it's not a superset of C.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.