我想确保static_assert在单元测试中正常工作。也就是说,如果我有一个
class MyClass {static_assert(my_type_trait<T>::value, "error"); };
然后在单元测试中MyClass<TypeWithTrait> myClass;
应该'通过'而MyClass<TypeWithoutTrait> myClass;
应该'失败'。
是否可以做这样的事情?
答案 0 :(得分:4)
如果要检查某些内容无法编译,则必须在代码外部进行测试。只需写一个简单的文件,如:
#include "MyClass.h"
int main() {
MyClass<%T%> m;
}
编写一个单元测试,用不同的%T%
值编译该文件。验证编译是否按预期成功,或者在失败文本中按预期失败并显示static_assert
。
答案 1 :(得分:-1)
Barry的建议是一种可能性,但如果你想要测试很多东西,你需要创建许多小文件。更重要的是,这些文件由于其他原因而无法编译而无法进行编译,从而错误地判断您的测试通过了。
另一种方法是,不使用static_assert
,而是使用某种SFINAE来检测是否有效。对于traits类,这有点棘手,但你可以这样做:
template <class T>
using void_t = void;
template <class T>
struct foo;
template <>
struct foo <double> {};
template <class T, class = void>
struct has_foo_trait : std::false_type {};
template <class T>
struct has_foo_trait<T, void_t<decltype(foo<T>{})>> : std::true_type {};
int main(int, char**) {
std::cerr << has_foo_trait<int>::value;
std::cerr << has_foo_trait<double>::value;
return 0;
}
打印出01
。所以现在,不是直接从static_assert
获得硬故障,而是可以在编译时计算特征存在的值,然后static_assert
得到你期望的值。
请注意,traits类很棘手的原因是因为trait被声明为一般模板,只是没有定义。所以做#&#34;通常&#34;元编程在void_t
内直接使用类型的东西不起作用。为了在true
的{{1}}分支中触发软SFINAE错误,我实际上必须默认构造traits类的实例。如果你写了你的特质课程,那么他们不是默认的可构造的,这不会起作用。但总的来说,你不会这样写。很想知道是否有更好的方法来做到这一点