是否存在static_warning? [英] Does there exist a static_warning?

查看:120
本文介绍了是否存在static_warning?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题提到了Boost的静态警告,但我会喜欢再次询问,具体来说,我如何实现 static_warning ,其操作类似于 static_assert ,但只会发出一个

我想要类似于Alexandrescu提出的在前C ++中的静态断言的建议,而不是中止编译错误。 11天,以某种方式设法打印一些有用的上下文信息作为错误的一部分。



这将是可以接受的,要求用户启用某些标准编译器警告,构造工作(也许是无效指针转换或打破严格别名规则) - 可以使用应该是正常编译的一部分的任何警告。



总之,我想要 static_warning(false,Hello world); 创建一个编译器警告,应该在警告消息中包含字符串hello world。这是可能的,例如在GCC和MSVC,以及如何?



我很乐意为任何特别聪明的解决方案给出一个小奖励奖励。






有一点解释:当我想到这个问题:静态警告将是跟踪复杂模板专门化的编译时过程的有用方法,否则很难调试。静态警告可以用作编译器发出的我现在正在编译这部分代码的简单信标。






更新。理想情况下,将在以下设置中触发警告:

 模板< typename T> struct Foo 
{
static_warning(std :: is_pointer< T> :: value,Attempting to use pointer type);
// ...
};

int main(){Foo< int>一个; Foo< int *> b; }


解决方案

>

  #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不支持此编译器
#endif

#define PP_CAT(x,y)PP_CAT1(x,y)
#define PP_CAT1(x,y)x ## y

命名空间detail
{
struct true_type {};
struct false_type {};
template< int test> struct converter:public true_type {};
模板<> struct converter< 0> :public false_type {};
}

#define STATIC_WARNING(cond,msg)\
struct PP_CAT(static_warning,__ LINE__){\
DEPRECATE(void _ :false_type const&),msg){}; \
void _(:: detail :: true_type const&){}; \
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter<(cond)>());} \
}

/ /注意:使用STATIC_WARNING_TEMPLATE以小的方式改变程序的含义。
//它引入了一个成员/变量声明。这意味着在每个结构/类实例化中至少有一个字节的空间
//。在任何
//非模板情况下,STATIC_WARNING应该是首选。
//'token'必须是一个程序范围的唯一标识符。
#define STATIC_WARNING_TEMPLATE(token,cond,msg)\
STATIC_WARNING(cond,msg)PP_CAT(PP_CAT(_localvar_,token),__ LINE__)
pre>

宏可以在命名空间,结构和函数作用域调用。给定输入:

  #line 1 
STATIC_WARNING(1 == 2,Failed with 1 and 2) ;
STATIC_WARNING(1 <2,成功与1和2);

struct Foo
{
STATIC_WARNING(2 == 3,2 and 3:oops);
STATIC_WARNING(2 <3,2和3工作);
};

void func()
{
STATIC_WARNING(3 == 4,3和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,模板警告);
};

template struct wrap< int> ;;

GCC 4.6(默认警告级别)会生成:



:$ static

static_warning.cpp:在构造函数'static_warning1 :: static_warning1()':
static_warning.cpp:1:1:warning:'void static_warning1 :: _ :false_type&)'
不推荐使用(在static_warning.cpp:1声明): 失败1和2 [-Wdeprecated-declarations]
static_warning .cpp:在构造函数'Foo :: static_warning6 :: static_warning6()':
static_warning.cpp:6:3:warning:'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:warning:'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:warning: void wrap< T> :: static_warning19 :: _(const detail :: false_type&)[with T = int]'
已弃用(在static_warning.cpp:19声明): 和5 [-Wdeprecated-declarations]

Visual C ++ 2010(位于/ W3或以上) :

 
warnproj.cpp(1):warning C4996:'static_warning1 :: _':Failed with 1 and 2
warnproj .cpp(1):参见声明'static_warning1 :: _'
warnproj.cpp(6):warning C4996:'Foo :: static_warning6 :: _':2和3:oops
warnproj。 cpp(6):参见声明'Foo :: static_warning6 :: _'
warnproj.cpp(12):warning C4996:'func :: static_warning12 :: _':3和4不太好
warnproj.cpp(12):参见声明'func :: static_warning12 :: _'
warnproj.cpp(19):warning C4996:'wrap< T> :: static_warning19 :: _': 4 and 5
with
[
T = int
]
warnproj.cpp(19):参见声明'wrap< T> :: static_warning19 :: _ '
with
[
T = int
]
warnproj.cpp(19):编译类模板成员函数'wrap< T> :: static_warning19 :: static_warning19(void)'
with
[
T = int
]
warnproj.cpp(24):参见类模板实例化wrap< T> ;: :static_warning19'正在编译
with
[
T = int
]

Clang ++ 3.1在Linux上生成可以更好的输出(颜色未显示):

 
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:注意:从宏'STATIC_WARNING'扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter< >());} \
^
tst3.cpp:6:3:警告:'_'已弃用:2和3:oops
[-Wdeprecated-declarations]
STATIC_WARNING(2 == 3,2 and 3:oops);
^
tst3.cpp:24:38:注意:从宏'STATIC_WARNING'扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter< >());} \
^
tst3.cpp:12:3:警告:'_'已弃用:3和4上不太好
[-Wdeprecated- ]
STATIC_WARNING(3 == 4,3和4不太好);
^
tst3.cpp:24:38:注意:从宏'STATIC_WARNING'扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter< >());} \
^
tst3.cpp:19:3:警告:_已弃用:4和5错误
[-Wdeprecated-declarations]
STATIC_WARNING(4 == 5,Bad with 4 and 5);
^
tst3.cpp:24:38:注意:从宏'STATIC_WARNING'扩展
PP_CAT(static_warning,__ LINE __)(){_(:: detail :: converter< >());} \
^
tst3.cpp:23:17:注意:在成员函数实例化时
'wrap< int> :: static_warning19 :: static_warning19' here
template struct wrap< int>
^
生成4个警告。


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:

#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__)

The macro can be invoked at namespace, structure, and function scope. Given the input:

#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 (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.

这篇关于是否存在static_warning?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆