您的位置:首页 > 编程语言

分享自定义静态断言代码

2012-11-21 09:20 1006 查看
本文代码来自于QQ群中nous大神,类似于static assert,不过断言异常内容可以自定义。

代码分为boost版本和标准版本,使用ENSURE_HAS_BOOST 宏来区分。

代码:

C++

//
// ensure.hpp
//
// Copyright (c) Nous Xiong.
//
// Macro ENSURE impl.
//
#ifndef ENSURE_HPP
#define ENSURE_HPP
#ifdef ENSURE_HAS_BOOST
#include <boost/exception/all>
#include <boost/thread/tss.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/integer.hpp>
#include <stdexcept>
#include <sstream>
#include <iostream>
namespace un
{
/// 运行时刻信息
typedef boost::error_info<struct tag_runtime, std::string> errinfo_runtime_t;
/// 专用于ensure的异常信息
typedef boost::error_info<struct tag_ensure, std::string> errinfo_ensure_t;
/// 异常基类
class exception
: public virtual std::exception
, public virtual boost::exception
{
};
class ensure
{
public:
ensure()
: current_function_(0)
, file_(0)
, line_(-1)
, msg_(0)
{
}
~ensure()
{
}
public:
ensure& set_context(char const* expr, char const* current_function, char const* file, int line)
{
msg_ = 0;
err_.str("");
err_ << "Ensure failed, expression: '" << expr << "', values: ";
current_function_ = current_function;
file_ = file;
line_ = line;
// 这里你可以将std::cerr替换为你自己项目的日志系统
std::cerr <<
"Ensure failed point: [" << file_ << "]=[" << line_ << "]" << std::endl;
return *this;
}
ensure& set_current_val(boost::int8_t src, char const* name)
{
boost::int32_t tmp = (boost::int32_t)src;
return set_val(tmp, name);
}
ensure& set_current_val(bool src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(boost::int16_t src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(boost::uint16_t src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(boost::int32_t src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(boost::uint32_t src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(boost::int64_t src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(boost::uint64_t src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(std::string const& src, char const* name)
{
err_ << name << " = " << src << ", size: " << src.size() << "; ";
return *this;
}
// 你可以加入任何你项目需要的数据类型
// 例如:
//ensure& set_current_val(my_data const& src, char const* name)
//{
// err_ << name << " = " << src.get_xxx() << "; ";
// return *this;
//}
/// 用户可添加的消息
ensure& set_current_val(char const* msg, char const*)
{
msg_ = msg;
return *this;
}
/// 抛出异常
template <typename ExceptT>
ensure& set_current_val(ExceptT const& ex, char const*)
{
if (msg_)
{
ex << errinfo_runtime_t(msg_);
}
ex << errinfo_ensure_t(err_.str());
boost::exception_detail::throw_exception_(ex, current_function_, file_, line_);
return *this;
}
static ensure& get_ensure()
{
// 为了多线程下方便的使用ensure,这里使用了线程本地存储,
// 如果是单线程程序,这里可以直接换为static ensure e;
static boost::thread_specific_ptr<ensure> this_ens;
ensure* ret = this_ens.get();
if (!ret)
{
this_ens.reset(new ensure);
ret = this_ens.get();
}
return *ret;
}
private:
template <typename T>
ensure& set_val(T const t, char const* name)
{
err_ << name << " = " << t << "; ";
return *this;
}
private:
std::stringstream err_;
char const* current_function_;
char const* file_;
int line_;
char const* msg_;
};
}
#define ENSURE_OP_IMPL(e, elem) e.set_current_val((elem), #elem); // 必须要定义这个宏,不然#elem无法正确的显示变量的字符串形式
#define ENSURE_OP(COLA_ENS, e, elem) ENSURE_OP_IMPL(e, elem)
#define ENSURE(expr, args) \
if( (expr) ) ; \
else \
{ \
un::ensure& e = un::ensure::get_ensure(); \
e.set_context(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__); \
BOOST_PP_SEQ_FOR_EACH(ENSURE_OP, e, args); \
}
#else
#include <stdexcept>
#include <sstream>
#include <iostream>
namespace un
{
class ensure
{
public:
ensure()
: ENSURE_A(*this)
, ENSURE_B(*this)
, file_(0)
, line_(-1)
, msg_(0)
{
}
~ensure()
{
}
ensure& ENSURE_A;
ensure& ENSURE_B;
public:
ensure& set_context(char const* expr, char const* file, int line)
{
msg_ = 0;
err_.str("");
err_ << "Ensure failed, expression: '" << expr << "', values: ";
file_ = file;
line_ = line;
// 这里你可以将std::cerr替换为你自己项目的日志系统
std::cerr <<
"Ensure failed point: [" << file_ << "]=[" << line_ << "]" << std::endl;
return *this;
}
ensure& set_current_val(char src, char const* name)
{
int tmp = (int)src;
return set_val(tmp, name);
}
ensure& set_current_val(bool src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(short src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(int src, char const* name)
{
return set_val(src, name);
}
ensure& set_current_val(std::string const& src, char const* name)
{
err_ << name << " = " << src << ", size: " << src.size() << "; ";
return *this;
}
// 你可以加入任何你项目需要的数据类型
// 例如:
//ensure& set_current_val(my_data const& src, char const* name)
//{
// err_ << name << " = " << src.get_xxx() << "; ";
// return *this;
//}
/// 用户可添加的消息
ensure& set_current_val(char const* msg, char const*)
{
msg_ = msg;
return *this;
}
/// 抛出异常
template <typename ExceptT>
ensure& set_current_val(ExceptT const& ex, char const*)
{
if (msg_)
{
err_ << "user msg = " << msg_;
}
ex.set_error(err_.str()); // 需要用户实现这个方法
throw ex;
return *this;
}
static ensure& get_ensure()
{
// 仅仅单线程
static ensure ret;
return ret;
}
private:
template <typename T>
ensure& set_val(T const t, char const* name)
{
err_ << name << " = " << t << "; ";
return *this;
}
private:
std::stringstream err_;
char const* file_;
int line_;
char const* msg_;
};
}
#define ENSURE_A(x) ENSURE_OP(x, B)
#define ENSURE_B(x) ENSURE_OP(x, A)
#define ENSURE_OP(x, next) \
ENSURE_A.set_current_val((x), #x).ENSURE_##next
#define ENSURE(expr) \
if( (expr) ) ; \
else un::ensure::get_ensure().set_context(#expr,__FILE__,__LINE__).ENSURE_A
#endif
#endif /* COLA_ENSURE_HPP */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
//
// ensure.hpp
//
// Copyright (c) Nous Xiong.
//
// Macro ENSURE impl.
//
 
#ifndef ENSURE_HPP
#define ENSURE_HPP
 
#ifdef ENSURE_HAS_BOOST
 
#include <boost/exception/all>
#include <boost/thread/tss.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/integer.hpp>
#include <stdexcept>
#include <sstream>
#include <iostream>
 

namespace un

{
/// 运行时刻信息

typedef boost::error_info<struct tag_runtime, std::string> errinfo_runtime_t;

 
/// 专用于ensure的异常信息

typedef boost::error_info<struct tag_ensure, std::string> errinfo_ensure_t;

 
/// 异常基类

class exception

  : public virtual std::exception

  , public virtual boost::exception

{

};

 

class ensure

{

public:

  ensure()

    : current_function_(0)

    , file_(0)

    , line_(-1)

    , msg_(0)

  {

  }

 

  ~ensure()

  {

  }

 

public:

  ensure& set_context(char const* expr, char const* current_function, char const* file, int line)

  {

    msg_ = 0;

    err_.str("");

    err_ << "Ensure failed, expression: '" << expr << "', values: ";

    current_function_ = current_function;

    file_ = file;

    line_ = line;

 

    // 这里你可以将std::cerr替换为你自己项目的日志系统

    std::cerr <<

      "Ensure failed point: [" << file_ << "]=[" << line_ << "]" << std::endl;

    return *this;

  }

 

  ensure& set_current_val(boost::int8_t src, char const* name)

  {

    boost::int32_t tmp = (boost::int32_t)src;

    return set_val(tmp, name);

  }

  ensure& set_current_val(bool src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(boost::int16_t src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(boost::uint16_t src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(boost::int32_t src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(boost::uint32_t src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(boost::int64_t src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(boost::uint64_t src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(std::string const& src, char const* name)

  {

    err_ << name << " = " << src << ", size: " << src.size() << "; ";

    return *this;

  }

  // 你可以加入任何你项目需要的数据类型

  // 例如:

  //ensure& set_current_val(my_data const& src, char const* name)

  //{

  //  err_ << name << " = " << src.get_xxx() << "; ";

  //  return *this;

  //}

 

  /// 用户可添加的消息

  ensure& set_current_val(char const* msg, char const*)

  {

    msg_ = msg;

    return *this;

  }

 

  /// 抛出异常

  template <typename ExceptT>

  ensure& set_current_val(ExceptT const& ex, char const*)

  {

    if (msg_)

    {

      ex << errinfo_runtime_t(msg_);

    }

    ex << errinfo_ensure_t(err_.str());

    boost::exception_detail::throw_exception_(ex, current_function_, file_, line_);

    return *this;

  }

 

  static ensure& get_ensure()

  {

    // 为了多线程下方便的使用ensure,这里使用了线程本地存储,

    // 如果是单线程程序,这里可以直接换为static ensure e;

    static boost::thread_specific_ptr<ensure> this_ens;

    ensure* ret = this_ens.get();

    if (!ret)

    {

      this_ens.reset(new ensure);

      ret = this_ens.get();

    }

    return *ret;

  }

 

private:

  template <typename T>

  ensure& set_val(T const t, char const* name)

  {

    err_ << name << " = " << t << "; ";

    return *this;

  }

 

private:

  std::stringstream err_;

  char const* current_function_;

  char const* file_;

  int line_;

  char const* msg_;

};

}
 
#define ENSURE_OP_IMPL(e, elem) e.set_current_val((elem), #elem); // 必须要定义这个宏,不然#elem无法正确的显示变量的字符串形式
#define ENSURE_OP(COLA_ENS, e, elem) ENSURE_OP_IMPL(e, elem)
 
#define ENSURE(expr, args) \

  if( (expr) ) ; \

  else \

  { \

    un::ensure& e = un::ensure::get_ensure(); \

    e.set_context(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__); \

    BOOST_PP_SEQ_FOR_EACH(ENSURE_OP, e, args); \

  }

 
#else
 
#include <stdexcept>
#include <sstream>
#include <iostream>
 

namespace un

{

class ensure

{

public:

  ensure()

    : ENSURE_A(*this)

    , ENSURE_B(*this)

    , file_(0)

    , line_(-1)

    , msg_(0)

  {

  }

 

  ~ensure()

  {

  }

 

  ensure& ENSURE_A;

  ensure& ENSURE_B;

 

public:

  ensure& set_context(char const* expr, char const* file, int line)

  {

    msg_ = 0;

    err_.str("");

    err_ << "Ensure failed, expression: '" << expr << "', values: ";

    file_ = file;

    line_ = line;

 

    // 这里你可以将std::cerr替换为你自己项目的日志系统

    std::cerr <<

      "Ensure failed point: [" << file_ << "]=[" << line_ << "]" << std::endl;

    return *this;

  }

 

  ensure& set_current_val(char src, char const* name)

  {

    int tmp = (int)src;

    return set_val(tmp, name);

  }

  ensure& set_current_val(bool src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(short src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(int src, char const* name)

  {

    return set_val(src, name);

  }

  ensure& set_current_val(std::string const& src, char const* name)

  {

    err_ << name << " = " << src << ", size: " << src.size() << "; ";

    return *this;

  }

  // 你可以加入任何你项目需要的数据类型

  // 例如:

  //ensure& set_current_val(my_data const& src, char const* name)

  //{

  //  err_ << name << " = " << src.get_xxx() << "; ";

  //  return *this;

  //}

 

  /// 用户可添加的消息

  ensure& set_current_val(char const* msg, char const*)

  {

    msg_ = msg;

    return *this;

  }

 

  /// 抛出异常

  template <typename ExceptT>

  ensure& set_current_val(ExceptT const& ex, char const*)

  {

    if (msg_)

    {

      err_ << "user msg = " << msg_;

    }

    ex.set_error(err_.str()); // 需要用户实现这个方法

    throw ex;

    return *this;

  }

 

  static ensure& get_ensure()

  {

    // 仅仅单线程

    static ensure ret;

    return ret;

  }

 

private:

  template <typename T>

  ensure& set_val(T const t, char const* name)

  {

    err_ << name << " = " << t << "; ";

    return *this;

  }

 

private:

  std::stringstream err_;

  char const* file_;

  int line_;

  char const* msg_;

};

}
 
#define ENSURE_A(x) ENSURE_OP(x, B)
#define ENSURE_B(x) ENSURE_OP(x, A)
 
#define ENSURE_OP(x, next) \

  ENSURE_A.set_current_val((x), #x).ENSURE_##next

 
#define ENSURE(expr) \

  if( (expr) ) ; \

  else un::ensure::get_ensure().set_context(#expr,__FILE__,__LINE__).ENSURE_A

 
#endif
 
#endif /* COLA_ENSURE_HPP */
测试代码:

C++

// ensure.cpp : Defines the entry point for the console application.
//
#include "ensure.hpp"
#ifdef ENSURE_HAS_BOOST
class my_except : public virtual un::exception {};
int main(int argc, char *argv[])
{
try
{
boost::int32_t i = 0;
std::string str("test str");
ENSURE(i == 0 && str.empty(), (i)(str)("Test Ensure Msg")(my_except()));
std::cout << "Shouldn't be here." << std::endl;
}
catch (my_except& ex)
{
std::cerr << boost::diagnostic_information(ex) << std::endl;
}
return 0;
}
#else
class my_except : public virtual std::exception
{
public:
void set_error(std::string const& err) const
{
err_ = err;
}
virtual char const* what() const throw()
{
return err_.c_str();
}
private:
mutable std::string err_;
};
int main(int argc, char *argv[])
{
try
{
int i = 0;
std::string str("test str");
ENSURE(i == 0 && str.empty())(i)(str)("Test Ensure Msg")(my_except());
std::cout << "Shouldn't be here." << std::endl;
}
catch (my_except& ex)
{
std::cerr << ex.what() << std::endl;
}
system("pause");
return 0;
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// ensure.cpp : Defines the entry point for the console application.
//
#include "ensure.hpp"
 
#ifdef ENSURE_HAS_BOOST
 

class my_except : public virtual un::exception {};

 

int main(int argc, char *argv[])

{

  try

  {

    boost::int32_t i = 0;

    std::string str("test str");

    ENSURE(i == 0 && str.empty(), (i)(str)("Test Ensure Msg")(my_except()));

    std::cout << "Shouldn't be here." << std::endl;

  }

  catch (my_except& ex)

  {

    std::cerr << boost::diagnostic_information(ex) << std::endl;

  }

 

    return 0;

}
 
#else
 

class my_except : public virtual std::exception

{

public:

  void set_error(std::string const& err) const

  {

    err_ = err;

  }

 

  virtual char const* what() const throw()

  {

    return err_.c_str();

  }

 

private:

  mutable std::string err_;

};

 

int main(int argc, char *argv[])

{

  try

  {

    int i = 0;

    std::string str("test str");

    ENSURE(i == 0 && str.empty())(i)(str)("Test Ensure Msg")(my_except());

    std::cout << "Shouldn't be here." << std::endl;

  }

  catch (my_except& ex)

  {

    std::cerr << ex.what() << std::endl;

  }

 

  system("pause");

  return 0;

}
 
#endif
ensure下载地址:

yunfile网盘百度网盘千军万马网盘Box网盘
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐