Pour faire suite au commentaire de Michael 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)>());} \
}
// Note: using STATIC_WARNING_TEMPLATE changes the meaning of a program in a small way.
// It introduces a member/variable declaration. This means at least one byte of space
// in each structure/class instantiation. STATIC_WARNING should be preferred in any
// non-template situation.
// 'token' must be a program-wide unique identifier.
#define STATIC_WARNING_TEMPLATE(token, cond, msg) \
STATIC_WARNING(cond, msg) PP_CAT(PP_CAT(_localvar_, token),__LINE__)
La macro peut être invoquée au niveau de l'espace de nom, de la structure et de la fonction. Étant donné l'entrée :
#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 (au niveau d'avertissement par défaut) produit :
static\_warning.cpp: In constructor ‘static\_warning1::static\_warning1()’:
static\_warning.cpp:1:1: warning: ‘void static\_warning1::\_(const detail::false\_type&)’
is deprecated (declared at static\_warning.cpp:1): **_Failed with 1 and 2_** \[-Wdeprecated-declarations\]
static\_warning.cpp: In constructor ‘Foo::static\_warning6::static\_warning6()’:
static\_warning.cpp:6:3: warning: ‘void Foo::static\_warning6::\_(const detail::false\_type&)’
is deprecated (declared at static\_warning.cpp:6): **_2 and 3: oops_** \[-Wdeprecated-declarations\]
static\_warning.cpp: In constructor ‘func()::static\_warning12::static\_warning12()’:
static\_warning.cpp:12:3: warning: ‘void func()::static\_warning12::\_(const detail::false\_type&)’
is deprecated (declared at static\_warning.cpp:12): **_Not so good on 3 and 4_** \[-Wdeprecated-declarations\]
static\_warning.cpp: In constructor ‘wrap<T>::static\_warning19::static\_warning19() \[with T = int\]’:
static\_warning.cpp:24:17: instantiated from here
static\_warning.cpp:19:3: warning: ‘void wrap<T>::static\_warning19::\_(const detail::false\_type&) \[with T = int\]’
is deprecated (declared at static\_warning.cpp:19): **_Bad with 4 and 5_** \[-Wdeprecated-declarations\]
Alors que Visual C++ 2010 (à /W3 ou plus) dit :
warnproj.cpp(1): warning C4996: 'static\_warning1::\_': Failed with 1 and 2
warnproj.cpp(1) : see declaration of 'static\_warning1::\_'
warnproj.cpp(6): warning C4996: 'Foo::static\_warning6::\_': 2 and 3: oops
warnproj.cpp(6) : see declaration of 'Foo::static\_warning6::\_'
warnproj.cpp(12): warning C4996: 'func::static\_warning12::\_': Not so good on 3 and 4
warnproj.cpp(12) : see declaration of 'func::static\_warning12::\_'
warnproj.cpp(19): warning C4996: 'wrap<T>::static\_warning19::\_': Bad with 4 and 5
with
\[
T=int
\]
warnproj.cpp(19) : see declaration of 'wrap<T>::static\_warning19::\_'
with
\[
T=int
\]
warnproj.cpp(19) : while compiling class template member function 'wrap<T>::static\_warning19::static\_warning19(void)'
with
\[
T=int
\]
warnproj.cpp(24) : see reference to class template instantiation 'wrap<T>::static\_warning19' being compiled
with
\[
T=int
\]
Clang++ 3.1 sur Linux produit une sortie sans doute plus belle (couleur non montrée) :
tst3.cpp:1:1: warning: '\_' is deprecated: Failed with 1 and 2
\[-Wdeprecated-declarations\]
STATIC\_WARNING(1==2, "Failed with 1 and 2");
^
tst3.cpp:24:38: note: expanded from macro 'STATIC\_WARNING'
PP\_CAT(static\_warning,\_\_LINE\_\_)() {\_(::detail::converter<(cond)>());} \\
^
tst3.cpp:6:3: warning: '\_' is deprecated: 2 and 3: oops
\[-Wdeprecated-declarations\]
STATIC\_WARNING(2==3, "2 and 3: oops");
^
tst3.cpp:24:38: note: expanded from macro 'STATIC\_WARNING'
PP\_CAT(static\_warning,\_\_LINE\_\_)() {\_(::detail::converter<(cond)>());} \\
^
tst3.cpp:12:3: warning: '\_' is deprecated: Not so good on 3 and 4
\[-Wdeprecated-declarations\]
STATIC\_WARNING(3==4, "Not so good on 3 and 4");
^
tst3.cpp:24:38: note: expanded from macro 'STATIC\_WARNING'
PP\_CAT(static\_warning,\_\_LINE\_\_)() {\_(::detail::converter<(cond)>());} \\
^
tst3.cpp:19:3: warning: '\_' is deprecated: Bad with 4 and 5
\[-Wdeprecated-declarations\]
STATIC\_WARNING(4==5, "Bad with 4 and 5");
^
tst3.cpp:24:38: note: expanded from macro 'STATIC\_WARNING'
PP\_CAT(static\_warning,\_\_LINE\_\_)() {\_(::detail::converter<(cond)>());} \\
^
tst3.cpp:23:17: note: in instantiation of member function
'wrap<int>::static\_warning19::static\_warning19' requested here
template struct wrap<int>
^
4 warnings generated.
0 votes
Recherchez-vous la portabilité ? Je sais que certains compilateurs implémentent des crochets similaires pour le préprocesseur (
#error
,#warning
,#message
), il serait peut-être judicieux de les implémenter dans gcc et Clang ?2 votes
@VioletGiraffe :
#warning
concerne les avertissements du préprocesseur, pour autant que je sache, et n'a rien à voir avec les instanciations de modèles.2 votes
GCC permet au
deprecated
à appliquer aux variables, aux types et aux fonctions ; il peut s'agir d'un message arbitraire (cf. gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html#Type-Attributes ). J'ai essayé d'élaborer une solution en l'utilisant, mais jusqu'à présent, les détails m'échappent ; il pourrait s'agir d'un composant de solution viable, cependant.