有些人(包括我自己)不喜欢 C++ const_cast<> 运算符的语法,因为;
- 它似乎命名错误,因为它删除
const。
- 它似乎违反了 DRY,因为它需要一个冗余类型 arg。
但我错了:它并没有错名,因为它也可以添加 const 和/或volatile "cv" 限定符,而且它只是部分违反 DRY,因为编译器会捕捉任何错误。所以我不太喜欢它并使用它:它比 C 风格的演员更安全。
使用 gcc 的 typeof,您可以在 C 中拥有几乎相同的类型安全性。
以下 C 代码示例给出了一个 CONST_CAST(T, x) 宏,并说明了它的用法:
#define REMOVE_QUALIFIER(cv, T, x) /* this macro evaluates its args only once */ \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), cv T), ((T)(x)), \
(void)0)
#define ADD_QUALIFIER(cv, T, x) /* this macro evaluates its args only once */ \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), T), ((cv T)(x)), \
(void)0)
#ifdef __GNUC__
#define CONST_CAST(T, x) REMOVE_QUALIFIER(const, T, x) // "misnamed"
#else
#define CONST_CAST(T, x) ((T)(x)) // fallback to standard C cast
#endif
void foo(void);
void foo(void) {
const int *a = 0;
const float *x = 0;
int *b = a; // warning
int *c = (int *)a; // no warning, unsafe standard cast
int *d = (int *)x; // no warning, and likely wrong
int *e = CONST_CAST(int *, a); // ok
int *f = CONST_CAST(int *, x); // error
unsigned *g = CONST_CAST(unsigned *, a); // error
const int **h = &b; // warning
const int **i = ADD_QUALIFIER(const, int **, &b); // ok
const int **j = ADD_QUALIFIER(const, int **, &x); // error
}
此技术还可用于更改类型的符号,让人想起 C++ 的 std::make_signed 和 std::make_unsigned,或 Boost 特征。例如:
#define MAKE_UNSIGNED(T, x) ADD_QUALIFIER(unsigned, T, x) // T usually char*