4

Suppose bad_name is a restricted identifier for example that I do not want to be part of the struct. I am looking for a mechanism to force a compilation failure in that case.

example.h

struct example {
  int okay_name;
  int bad_name; 
}

main.cc

#include "example.h"

int main() {
  example ex;
  // cause compilation to fail here if bad_name is a member of ex

  return 0;
}

There are probably ways to cause a failure at runtime by simulating reflection, but is there a way to do this at compile time?

Lazer
  • 90,700
  • 113
  • 281
  • 364

4 Answers4

4

You can define bad_name to be something that would cause a compile time error. For example, nothing:

#define bad_name

gives on GCC

error: declaration does not declare anything [-fpermissive]

int bad_name;

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
4

You can simulate static assertions in C like this:

#define bad_name xxx; char static_assertion_bad_name_used[-1];

struct example {
  int okay_name;
  int bad_name;
};

which in GCC gives:

main.c:6: error: size of array ‘static_assertion_bad_name_used’ is negative

The advantage of this technique is that the error message gives you a reminder of what the problem is (even if slightly obscurely).

Update After reading this I found out that MS Visual Studio does not include the actual variable name in the error message if the array size is negative. Here is an alternative:

#define bad_name xxx; int static_assertion_bad_name_used : 0;

The error message in GCC is then:

main.c:5: error: zero width for bit-field ‘static_assertion_bad_name_used’

and apparently something similar in VS.

Also if using a more up to date compiler you can use _Static_assert, which would be a lot cleaner.

Community
  • 1
  • 1
harmic
  • 28,606
  • 5
  • 67
  • 91
1

You may use the following:

#include <cstdint>

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               \
    template <typename U>                                                   \
    class traitsName                                                        \
    {                                                                       \
    private:                                                                \
        template<typename T, T> struct helper;                              \
        template<typename T>                                                \
        static std::uint8_t check(helper<signature, &funcName>*);           \
        template<typename T> static std::uint16_t check(...);               \
    public:                                                                 \
        static                                                              \
        constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
    }

DEFINE_HAS_SIGNATURE(has_bad_name, T::bad_name, decltype(&T::bad_name));

Then check with a static_assert (need C++11):

static_assert(!has_bad_name<example>::value, "");
Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

Suppose bad_name is a restricted identifier for example that I do not want to be part of the struct. I am looking for a mechanism to force a compilation failure in that case.

This is not fully portable, but at least in VC++ and GCC you can mark the identifier as deprecated and, if you want, elevate the warning it gives to an error.

Community
  • 1
  • 1
D Drmmr
  • 1,223
  • 8
  • 15