0

I have to implement a linked list data structure in C. In "linked_list.h" header file I have the following line:

typedef int ListDataType;

My question is, how can I terminate the program if ListDataType is not equal to int? I know that the preprocessor can't prevent my program from compiling in case this requirement is not met (because it knows nothing about typedefs).

I code in C11, and I know about _Generic keyword. How can I avoid writing such things as the following?

{
  ListDataType q;
  const bool kListDataTypeIsNotInt = _Generic(q, int: false, default: true);
  if (kListDataTypeIsNotInt) {
    print_error_message_and_exit("list data types other than int are not supported");
  }
}

Should I use the macro (#define LIST_DATA_TYPE int) instead?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • If you write the header file and control the type-alias, why would you ever make it something that is invalid? What is the problem that such a check would solve? – Some programmer dude Oct 31 '20 at 09:53
  • @Someprogrammerdude, if someone edits my code to use lists containing `char *` for example, this will prevent the code from undesired behavior. – memoryallocator Oct 31 '20 at 09:59
  • What's to prevent that someone to edit the check as well? As a library-author you can't prevent the users of your library to do stupid things. Just remember to document everything, and adding the disclaimer "if you modify anything then you're on your own" (or similar). Then if a user that did just such a change complains about the code breaking, you can just reply back !it was you who broke it, now go away" (perhaps phrased a little more diplomatic). – Some programmer dude Oct 31 '20 at 10:03
  • And why do you want to avoid `_Generic`? – Olaf Dietsche Oct 31 '20 at 10:06
  • @Someprogrammerdude, this is the part of my university task, and the description of my task explicitly stated that a student should implement a list of `int`s. So it was my initiative to introduce that `ListDataType`. I just wanted my code to look more maintainable, and I don't think it will be ever used in production. Thank you for your answer anyway! Maybe it is actually an overengineering. – memoryallocator Oct 31 '20 at 10:11
  • @OlafDietsche, I don't want to avoid `_Generic` itself but rather that ugly piece of code (and creating an unnecessary variable). Unfortunately, it seems there is no way to do so, and I'll use `_Generic` if there is really no other solution. – memoryallocator Oct 31 '20 at 10:15
  • I suspect a) this is a XY problem b) this might help you https://stackoverflow.com/q/58280538/7733418 – Yunnosch Oct 31 '20 at 10:53

1 Answers1

1

The variable in your code will get optimized away and I strongly suspect this code will be 100% compile-time after optimizations.

Still, if you are uncertain, you could tweak it ever so slightly by introducing a macro and a static assertion:

#define IS_INT(q) _Generic((q), int: true, default: false)
...

ListDataType q;
_Static_assert(IS_INT(q), "list data types other than int are not supported");

This is 100% compile-time and good practice.

Lundin
  • 195,001
  • 40
  • 254
  • 396