如果存在具有特定名称的结构成员,则强制编译失败

时间:2014-04-15 05:54:00

标签: c++

假设bad_name是受限制的标识符,例如我不想成为结构的一部分。我正在寻找一种机制来强制在这种情况下编译失败。

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;
}

有可能通过模拟反射在运行时导致失败,但有没有办法在编译时执行此操作?

4 个答案:

答案 0 :(得分:4)

您可以将bad_name定义为会导致编译时错误的内容。例如,什么都没有:

#define bad_name

给出GCC

  

错误:声明没有声明任何内容[-fpermissive]

     

int bad_name;

答案 1 :(得分:4)

您可以在C中模拟静态断言:

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

struct example {
  int okay_name;
  int bad_name;
};

在GCC中给出:

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

这种技术的优点是错误信息可以提醒您问题是什么(即使有点模糊)。

更新阅读this后,如果数组大小为负,我发现MS Visual Studio在错误消息中不包含实际的变量名。这是另一种选择:

#define bad_name xxx; int static_assertion_bad_name_used : 0;

GCC中的错误消息是:

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

在VS中显然有类似的东西。

此外,如果使用更新的编译器,您可以使用_Static_assert,这将更加清晰。

答案 2 :(得分:1)

您可以使用以下内容:

#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));

然后检查static_assert(需要C ++ 11):

static_assert(!has_bad_name<example>::value, "");

答案 3 :(得分:0)

  

假设bad_name是受限制的标识符,例如我不是   想成为结构的一部分。我正在寻找一种强制机制   在这种情况下编译失败。

这不是完全可移植的,但至少在VC ++和GCC中,您可以将标识符标记为deprecated,如果需要,可以提升它给出的错误警告。