淡化迈克尔E的评论:
#if defined(__GNUC__)
#define DEPRECATE(foo, msg) foo __attribute__((deprecated(msg)))
#elif defined(_MSC_VER)
#define DEPRECATE(foo, msg) __declspec(deprecated(msg)) foo
#else
#error This compiler is not supported
#endif
#define PP_CAT(x,y) PP_CAT1(x,y)
#define PP_CAT1(x,y) x##y
namespace detail
{
struct true_type {};
struct false_type {};
template <int test> struct converter : public true_type {};
template <> struct converter<0> : public false_type {};
}
#define STATIC_WARNING(cond, msg) \
struct PP_CAT(static_warning,__LINE__) { \
DEPRECATE(void _(::detail::false_type const& ),msg) {}; \
void _(::detail::true_type const& ) {}; \
PP_CAT(static_warning,__LINE__)() {_(::detail::converter<(cond)>());} \
}
#define STATIC_WARNING_TEMPLATE(token, cond, msg) \
STATIC_WARNING(cond, msg) PP_CAT(PP_CAT(_localvar_, token),__LINE__)
可以在名称空间,结构和功能范围内调用该宏。给定输入:
#line 1
STATIC_WARNING(1==2, "Failed with 1 and 2");
STATIC_WARNING(1<2, "Succeeded with 1 and 2");
struct Foo
{
STATIC_WARNING(2==3, "2 and 3: oops");
STATIC_WARNING(2<3, "2 and 3 worked");
};
void func()
{
STATIC_WARNING(3==4, "Not so good on 3 and 4");
STATIC_WARNING(3<4, "3 and 4, check");
}
template <typename T> struct wrap
{
typedef T type;
STATIC_WARNING(4==5, "Bad with 4 and 5");
STATIC_WARNING(4<5, "Good on 4 and 5");
STATIC_WARNING_TEMPLATE(WRAP_WARNING1, 4==5, "A template warning");
};
template struct wrap<int>;
GCC 4.6(默认警告级别)产生:
static_warning.cpp:在构造函数“ static_warning1 :: static_warning1()”中:
static_warning.cpp:1:1:警告:'无效static_warning1 :: __(const detail :: false_type&)'
被弃用(在static_warning.cpp:1处声明):失败,出现1和2 [-Wdeprecated-declarations]
static_warning.cpp:在构造函数“ Foo :: static_warning6 :: static_warning6()”中:
static_warning.cpp:6:3:警告:'void Foo :: static_warning6 :: __(const detail :: false_type&)'
已弃用(在static_warning.cpp:6处声明):2和3:oops [-Wdeprecated-declarations]
static_warning.cpp:在构造函数'func():: static_warning12 :: static_warning12()'中:
static_warning.cpp:12:3:警告:'void func():: static_warning12 :: _(const detail :: false_type&)'
不推荐使用(在static_warning.cpp:12声明):在3和4上不太好[-Wdeprecated-declarations]
static_warning.cpp:在构造函数'wrap <T> :: static_warning19 :: static_warning19()[with T = int]'中:
static_warning.cpp:24:17:从此处实例化
static_warning.cpp:19:3:警告:“无效包装<T> :: static_warning19 :: _(const detail :: false_type&)[with T = int]”
被弃用(在static_warning.cpp:19处声明):不好,包含4和5 [-Wdeprecated-declarations]
虽然Visual C ++ 2010(/ W3或更高版本)说:
warnproj.cpp(1):警告C4996:'static_warning1 :: _':失败为1和2
warnproj.cpp(1):请参见“ static_warning1 :: _”的声明
warnproj.cpp(6):警告C4996:'Foo :: static_warning6 :: _':2和3:哎呀
warnproj.cpp(6):参见'Foo :: static_warning6 :: _'的声明
warnproj.cpp(12):警告C4996:'func :: static_warning12 :: _':在3和4上不太好
warnproj.cpp(12):参见'func :: static_warning12 :: _'的声明
warnproj.cpp(19):警告C4996:'wrap <T> :: static_warning19 :: _':4和5错误
与
[
T =整数
]
warnproj.cpp(19):参见'wrap <T> :: static_warning19 :: _'的声明
与
[
T =整数
]
warnproj.cpp(19):编译类模板成员函数'wrap <T> :: static_warning19 :: static_warning19(void)'时
与
[
T =整数
]
warnproj.cpp(24):请参见对正在编译的类模板实例化'wrap <T> :: static_warning19'的引用
与
[
T =整数
]
Linux上的Clang ++ 3.1产生了更好的输出(未显示颜色):
tst3.cpp:1:1:警告:不推荐使用'_':失败1和2
[-Wdeprecated-clarations]
STATIC_WARNING(1 == 2,“失败的1和2”);
^
tst3.cpp:24:38:注意:从宏“ STATIC_WARNING”扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter <(cond)>());} \
^
tst3.cpp:6:3:警告:不推荐使用'_':2和3:哎呀
[-Wdeprecated-clarations]
STATIC_WARNING(2 == 3,“ 2 and 3:oops”);
^
tst3.cpp:24:38:注意:从宏“ STATIC_WARNING”扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter <(cond)>());} \
^
tst3.cpp:12:3:警告:不推荐使用'_':在3和4上效果不佳
[-Wdeprecated-clarations]
STATIC_WARNING(3 == 4,“在3和4上不太好”);
^
tst3.cpp:24:38:注意:从宏“ STATIC_WARNING”扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter <(cond)>());} \
^
tst3.cpp:19:3:警告:不推荐使用'_':4和5错误
[-Wdeprecated-clarations]
STATIC_WARNING(4 == 5,“错误的4和5”);
^
tst3.cpp:24:38:注意:从宏“ STATIC_WARNING”扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter <(cond)>());} \
^
tst3.cpp:23:17:注意:在成员函数的实例化中
这里要求'wrap <int> :: static_warning19 :: static_warning19'
模板struct wrap <int>
^
生成4条警告。
#error
,, )实现了类似的钩子#warning
,#message
因此也许在gcc和Clang中实现这些钩子有意义吗?