I’m aware of this question which mentions Boost’s “STATIC WARNING”, but I’d like to ask again, specifically, how I could implement a static_warning which operates similarly to static_assert but only emits a warning at compile time rather than an aborting compilation error.
I’d like something similar to Alexandrescu’s proposal for a static assert in pre-C++11 days which somehow managed to print some useful contextual information as part of the error.
It would be acceptable to require that the user enable certain standard compiler warnings in order for this construction to work (perhaps “invalid pointer conversion” or “breaks strict aliasing rules”) — any warning that should be part of a normal compilation anyway can be used.
In short, I want static_warning(false, "Hello world"); to create a compiler warning that should somehow include the string “hello world” in the warning message. Is this possible, say in GCC and MSVC, and how?
I’d happily give out a small reward bounty for any particularly clever solution.
As a bit of explanation: I got the idea when thinking about this question: A static warning would be a useful way to trace through the compile-time process of complex template specializations, which are otherwise fairly hard to debug. A static warning could be used as a simple beacon for the compiler to emit “I’m now compiling this part of the code.”
Update. Ideally, the warning would be triggered in the following setup:
template <typename T> struct Foo
{
static_warning(std::is_pointer<T>::value, "Attempting to use pointer type.");
// ...
};
int main() { Foo<int> a; Foo<int*> b; }
Playing off of Michael E’s comment:
The macro can be invoked at namespace, structure, and function scope. Given the input:
GCC 4.6 (at default warning level) produces:
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]While Visual C++ 2010 (at /W3 or above) says:
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 on Linux produces the arguably nicer output (color not shown):
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.