因为在我工作的公司中禁止提升,所以我需要在纯C++中实现它的功能。我已经研究过助推源,但他们似乎太复杂,至少对我来说是无法理解的。我知道在C++ 0x standart中有一个叫static_assert()
的东西,但我不想使用任何C++ 0x功能。BOOST_STATIC_ASSERT没有提升
回答
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};
int main() {
StaticAssert< (4>3) >(); //OK
StaticAssert< (2+2==5) >(); //ERROR
}
+1够简单,但我喜欢有一个与断言相关的消息 – 2009-12-30 14:07:16
@Gregory:'StaticAssert < (2+2==5) > associatedMessage();' – 2009-12-30 17:19:01
有些地方你不想/不能使用变量虽然 – 2009-12-30 19:34:52
你可以从Boost source file宏简单地复制到自己的代码。如果您不需要支持Boost支持的所有编译器,您可以为编译器选择正确的定义,并省略该文件中其余的#ifdef
。
这是合法的Boost的许可证吗? – gatopeich 2011-06-07 17:41:05
其他一招(其可以在C中使用的)是试图建立一个数组具有负的大小,如果断言失败:
#define ASSERT(cond) int foo[(cond) ? 1 : -1]
作为奖励,你可以使用一个typedef,而不是一个对象,因此,它在多个环境可用,并没有发生,当它成功:
#define ASSERT(cond) typedef int foo[(cond) ? 1 : -1]
最后,建立一个名称与名称冲突的机会更少(和可重复使用至少在不同线路):
#define CAT_(a, b) a ## b
#define CAT(a, b) CAT_(a, b)
#define ASSERT(cond) typedef int CAT(AsSeRt, __LINE__)[(cond) ? 1 : -1]
有人可以解释为什么两个CAT宏是必要的吗?你想避免什么问题?谢谢。 – grokus 2010-12-16 20:24:50
如果你不这样做,宏的参数(如'__LINE__')不会被扩展。所以它会生成'AsSeRt__LINE__'而不是想要的'AsSeRt42'。我很确定有一个问题在某处详细解释了这一点。 – AProgrammer 2010-12-17 14:58:37
我使用下面的头文件,用代码从别人撕开......
#ifndef STATIC_ASSERT__H
#define STATIC_ASSERT__H
/* ripped from http://www.pixelbeat.org/programming/gcc/static_assert.html */
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
/* microsoft */
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
/* This can't be used twice on the same line so ensure if using in headers
* that the headers are not included twice (by wrapping in #ifndef...#endif)
* Note it doesn't cause an issue when used on same line of separate modules
* compiled with gcc -combine -fwhole-program. */
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif
/* http://msdn.microsoft.com/en-us/library/ms679289(VS.85).aspx */
#ifndef C_ASSERT
#define C_ASSERT(e) STATIC_ASSERT(e)
#endif
#endif
这是我自己实现从我的代码库中提取静态断言的:Pre-C++11 Static Assertions Without Boost
。
用法:
STATIC_ASSERT(expression, message);
当静态断言测试失败,则生成以某种方式包含STATIC_ASSERTION_FAILED_AT_LINE_xxx_message
一个编译器的错误消息。
message
必须是一个有效的C++标识符,如no_you_cant_have_a_pony
这将产生含有编译器错误:
STATIC_ASSERTION_FAILED_AT_LINE_1337_no_you_cant_have_a_pony
:)
#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2) arg1##arg2
/**
* Usage:
*
* <code>STATIC_ASSERT(expression, message)</code>
*
* When the static assertion test fails, a compiler error message that somehow
* contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated.
*
* /!\ message has to be a valid C++ identifier, that is to say it must not
* contain space characters, cannot start with a digit, etc.
*
* STATIC_ASSERT(true, this_message_will_never_be_displayed);
*/
#define STATIC_ASSERT(expression, message)\
struct CONCATENATE(__static_assertion_at_line_, __LINE__)\
{\
implementation::StaticAssertion<static_cast<bool>((expression))> CONCATENATE(CONCATENATE(CONCATENATE(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\
};\
typedef implementation::StaticAssertionTest<sizeof(CONCATENATE(__static_assertion_at_line_, __LINE__))> CONCATENATE(__static_assertion_test_at_line_, __LINE__)
// note that we wrap the non existing type inside a struct to avoid warning
// messages about unused variables when static assertions are used at function
// scope
// the use of sizeof makes sure the assertion error is not ignored by SFINAE
namespace implementation {
template <bool>
struct StaticAssertion;
template <>
struct StaticAssertion<true>
{
}; // StaticAssertion<true>
template<int i>
struct StaticAssertionTest
{
}; // StaticAssertionTest<int>
} // namespace implementation
STATIC_ASSERT(true, ok);
STATIC_ASSERT(false, ko);
int main()
{
return 0;
}
+1“no_you_cant_have_a_pony” – 2009-12-31 02:45:49
非常好!这是一个完整的解决方案(如果你想避免自我提升,那么这是一个很好的替代方案)+1 – Samaursa 2013-03-09 20:40:21
我认为这应该工作:
template<bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true>{};
#define STATIC_ASSERT(e) (CompileTimeAssert <(e) != 0>())
- 1. BOOST_FOREACH没有提升?
- 2. Asio没有提升
- 3. CMake没有找到提升
- 4. 项目建设有和没有提升
- 5. 如何使用BOOST_STATIC_ASSERT
- 6. Parallel.ForEach和Regex没有性能提升吗?
- 7. gnuplot-iostream没有链接到提升
- 8. 提升make_shared没有模板参数
- 9. cmake没有找到提升库
- 10. boost ::线程没有全部提升?
- 11. WampServer上的APC没有性能提升
- 12. 为什么工具栏没有提升?
- 13. enable_if +类型模板,没有SFINAE(enable_if_c没有提升?)
- 14. 哪个更好BOOST_MPL_ASSERT或BOOST_STATIC_ASSERT?
- 15. 使用存储过程有没有主要的性能提升?
- 16. 有没有不需要提升的连接器/ C++库?
- 17. C#TryParse有没有提升lexical_cast等价物?
- 18. 用Webpack捆绑ES6类。有没有办法提升扩展类?
- 19. 有没有办法关闭提升日期和时间验证
- 20. tortoiseSVN 1.8升级没有升级svn.exe
- 21. 提升库和持有值
- 22. BOOST_STATIC_ASSERT的名称空间范围
- 23. 升压program_options没有找到
- 24. 提升线程和提升Asio
- 25. 提升为Android建设提升日志
- 26. 索引时间文件提升没有考虑到
- 27. OPcache计数缓存命中,但没有性能提升
- 28. 如何(交叉)编译提升没有python?
- 29. 管道提升:: iostreams没有任何输出
- 30. 提升缓冲成char *(没有的std :: string)
做你问为什么你不允许使用提升? – 2009-12-30 14:05:49
@Gregory Pakosz,他们说,因为它太复杂了:) – Konstantin 2009-12-30 22:26:49