您可以使用 assert 来测试 C++ 中的类型定义吗?
Posted
技术标签:
【中文标题】您可以使用 assert 来测试 C++ 中的类型定义吗?【英文标题】:Can you use assert to test type defintions in C++? 【发布时间】:2011-09-26 18:58:26 【问题描述】:我可以使用assert 来强制执行类型定义吗?假设有一个变量double d
,你怎么能用assert
断言d是一个double呢?如果assert
不适用(我打赌不适用),还有其他选择吗?我特别希望在调试期间测试隐式类型转换,同时受益于assert
和#define NDEBUG
的功能。
附言 显然,我想将它用于任何类型定义,这里仅使用 double 作为示例。解决方案应该是跨平台兼容的,并且兼容C++03。
我喜欢在我的类设置器中添加错误检查。例如,假设有一个类 MyClass,它有一个私有成员变量 x:
void MyClass::setX(double input)
// assert x is double
x = input;
【问题讨论】:
assert() 用于运行时检查。对于数据类型,您可以使用更强大的工具 - 编译时检查。描述一个具体的场景,也许 SO 集体会想办法把它变成编译错误的情况。 无论在哪里定义x
,都将类型设为double
。
@Gman,我喜欢在设置器中添加错误检查以确保稳健性。
我是 C++ 新手,你能告诉我在什么情况下 double 声明的参数可能是别的东西?谢谢
@NiklasR:他似乎想要断言 member 是否是别的东西。无法想象那会是怎样。
【参考方案1】:
这实际上是一个编译时检查,所以你应该为此使用静态断言。
这是一个使用 boost 的静态断言和类型特征的示例。
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
template<typename T>
void some_func()
BOOST_STATIC_ASSERT( (boost::is_same<double, T>::value) );
TEST(type_check)
some_func<double>();
我假设你的意思是模板。
【讨论】:
那是BOOST_STATIC_ASSERT
,它可能需要双括号,因为参数有一个逗号。
@K-ballo 你说得对,先生,我已经纠正了。想象一下我的耻辱。【参考方案2】:
您可以使用type_info
class 中定义的==
运算符来测试特定类型定义。
#include <assert.h>
#include <iostream>
#include <typeinfo>
int main ()
double a = 0;
std::cout << typeid(a).name() << std::endl;
assert(typeid(a)==typeid(double));
assert(typeid(a)==typeid(int)); // FAIL
或者使用模板和 try/catch 从另一个 SO answer 借用:
#include <assert.h>
#include <iostream>
#include <typeinfo>
template <typename X, typename A>
inline void Assert(A assertion)
if( !assertion ) throw X();
#ifdef NDEBUG
const bool CHECK_ASSERT = false;
#else
const bool CHECK_ASSERT = true;
#endif
struct Wrong ;
int main ()
double a = 0;
std::cout << typeid(a).name() << std::endl;
assert(typeid(a)==typeid(double));
Assert<Wrong>(!CHECK_ASSERT || typeid(a)==typeid(double));
try
//assert(typeid(a)==typeid(int)); // FAIL and Abort()
Assert<Wrong>(!CHECK_ASSERT || typeid(a)==typeid(int)); // FALL
catch (Wrong)
std::cerr <<"Exception, not an int" <<std::endl;
【讨论】:
【参考方案3】:您应该能够使用std::is_same
和decltype
进行比较。您甚至可以使用std::static_assert
将检查移动到编译时间。我已经看到它发生在 libc++ 中:)
请注意,这些是 C++11 功能,因此您需要有一个支持 decltype
的编译器
【讨论】:
应该是std::is_same
,注意基于 C++03 的解决方案仍然是可能的,但是问题中没有足够的上下文信息来提出这样的建议。在 C++11 世界中,static_assert 也更适合一次。
@K-ballo C++03 还需要什么其他上下文?【参考方案4】:
鉴于代码的当前定义,在编译时检查两者是否属于同一类型的方法是:
template< typename T, typename U >
void assert_same_type( T const&, U const& )
int error[ sizeof( T ) ? -1 : -2 ]; // error array of negative size, dependent on T otherwise some implementations may cause an early error message even when they shouldn't
template< typename T >
void assert_same_type( T&, T& )
void MyClass::setX(double input)
assert_same_type( x, input ); // If the fallback case is instantiated then a compile time error will arise of trying to declare an array of negative size.
x = input;
【讨论】:
@rubenvb:我不确定是否真的是这样,但如果只是在后备案例中添加一个错误。我会更新我的答案。【参考方案5】:您可以创建一个模板函数,然后像这样重载double
的参数类型:
#include <cassert>
template<class T>
bool is_double(T) return false;
bool is_double(double) return true;
int main()
int i = 1;
double d = 3.14;
assert( is_double(d) );
assert( is_double(i) ); // fails
这会产生运行时错误。您可以通过简单地定义一个采用双重引用的函数来生成编译时错误:
void is_double(double&)
void MyClass::setX(double input)
is_double(x); // assert x is double
x = input;
【讨论】:
以上是关于您可以使用 assert 来测试 C++ 中的类型定义吗?的主要内容,如果未能解决你的问题,请参考以下文章