Ausspielung von Michael E's Kommentar:
#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__)
Das Makro kann im Namespace, in der Struktur und im Funktionsumfang aufgerufen werden. Angesichts der Eingabe:
#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 (auf Standardwarnstufe) erzeugt:
static_warning.cpp: Im Konstruktor 'static_warning1 :: static_warning1 ()':
static_warning.cpp: 1: 1: Warnung: 'void static_warning1 :: _ (const detail :: false_type &)'
ist veraltet (deklariert bei static_warning.cpp: 1): Fehler mit 1 und 2 [-Wdeprecated-Deklarationen]
static_warning.cpp: Im Konstruktor 'Foo :: static_warning6 :: static_warning6 ()':
static_warning.cpp: 6: 3: Warnung: 'void Foo :: static_warning6 :: _ (const detail :: false_type &)'
ist veraltet (deklariert bei static_warning.cpp: 6): 2 und 3: oops [-Wdeprecated-declarations]
static_warning.cpp: Im Konstruktor 'func () :: static_warning12 :: static_warning12 ()':
static_warning.cpp: 12: 3: Warnung: 'void func () :: static_warning12 :: _ (const detail :: false_type &)'
ist veraltet (deklariert bei static_warning.cpp: 12): Nicht so gut bei 3 und 4 [-Wdeprecated-Deklarationen]
static_warning.cpp: Im Konstruktor 'wrap <T> :: static_warning19 :: static_warning19 () [mit T = int]':
static_warning.cpp: 24: 17: von hier aus instanziiert
static_warning.cpp: 19: 3: Warnung: 'void wrap <T> :: static_warning19 :: _ (const detail :: false_type &) [mit T = int]'
ist veraltet (deklariert bei static_warning.cpp: 19): Bad mit 4 und 5 [-Wdeprecated-Deklarationen]
Während Visual C ++ 2010 (bei / W3 oder höher) sagt:
warnproj.cpp (1): Warnung C4996: 'static_warning1 :: _': Fehler mit 1 und 2
warnproj.cpp (1): siehe Deklaration von 'static_warning1 :: _'
warnproj.cpp (6): Warnung C4996: 'Foo :: static_warning6 :: _': 2 und 3: oops
warnproj.cpp (6): siehe Deklaration von 'Foo :: static_warning6 :: _'
warnproj.cpp (12): Warnung C4996: 'func :: static_warning12 :: _': Nicht so gut bei 3 und 4
warnproj.cpp (12): siehe Deklaration von 'func :: static_warning12 :: _'
warnproj.cpp (19): Warnung C4996: 'wrap <T> :: static_warning19 :: _': Schlecht mit 4 und 5
mit
[
T = int
]]
warnproj.cpp (19): siehe Deklaration von 'wrap <T> :: static_warning19 :: _'
mit
[
T = int
]]
warnproj.cpp (19): Beim Kompilieren der Klassenvorlagenelementfunktion 'wrap <T> :: static_warning19 :: static_warning19 (void)'
mit
[
T = int
]]
warnproj.cpp (24): Siehe Verweis auf die Instanziierung der Klassenvorlage 'wrap <T> :: static_warning19', die kompiliert wird
mit
[
T = int
]]
Clang ++ 3.1 unter Linux erzeugt die wohl schönere Ausgabe (Farbe nicht gezeigt):
tst3.cpp: 1: 1: Warnung: '_' ist veraltet: Fehlgeschlagen mit 1 und 2
[Veraltete Erklärungen]
STATIC_WARNING (1 == 2, "Fehlgeschlagen mit 1 und 2");
^
tst3.cpp: 24: 38: Hinweis: erweitert vom Makro 'STATIC_WARNING'
PP_CAT (static_warning, __ LINE __) () {_ (:: detail :: converter <(cond)> ());} \
^
tst3.cpp: 6: 3: Warnung: '_' ist veraltet: 2 und 3: oops
[Veraltete Erklärungen]
STATIC_WARNING (2 == 3, "2 und 3: oops");
^
tst3.cpp: 24: 38: Hinweis: erweitert vom Makro 'STATIC_WARNING'
PP_CAT (static_warning, __ LINE __) () {_ (:: detail :: converter <(cond)> ());} \
^
tst3.cpp: 12: 3: Warnung: '_' ist veraltet: Nicht so gut bei 3 und 4
[Veraltete Erklärungen]
STATIC_WARNING (3 == 4, "Nicht so gut bei 3 und 4");
^
tst3.cpp: 24: 38: Hinweis: erweitert vom Makro 'STATIC_WARNING'
PP_CAT (static_warning, __ LINE __) () {_ (:: detail :: converter <(cond)> ());} \
^
tst3.cpp: 19: 3: Warnung: '_' ist veraltet: Schlecht mit 4 und 5
[Veraltete Erklärungen]
STATIC_WARNING (4 == 5, "Schlecht mit 4 und 5");
^
tst3.cpp: 24: 38: Hinweis: erweitert vom Makro 'STATIC_WARNING'
PP_CAT (static_warning, __ LINE __) () {_ (:: detail :: converter <(cond)> ());} \
^
tst3.cpp: 23: 17: Hinweis: zur Instanziierung der Mitgliedsfunktion
'wrap <int> :: static_warning19 :: static_warning19' wird hier angefordert
Template Struct Wrap <int>
^
4 Warnungen generiert.
#error
,#warning
,#message
) so vielleicht , dass es Sinn machen würde , um tatsächlich die in gcc und Clang zu implementieren?