如何预期static_assert失败并使用Boost.Test框架进行处理
How to expect a static_assert failure and deal with it using Boost.Test framework?
如果我有一个方法接受一个模板参数,该参数应该转换为、base_of或与返回的类型相同的类型,我应该怎么做?
例如,考虑这种方法:
template <class T>
class IFoo
{
public:
template <class ServiceT>
T* as()
{
static_assert(std::is_same< T, ServiceT >::value
|| std::is_convertible< T, ServiceT >::value
|| std::is_base_of< ServiceT, T >::value,
"IFoo< T >::as< ServiceT >() requires ServiceT to be a base of T");
...
}
};
现在,我想BOOST_CHECK!
class A {};
class B {};
BOOST_AUTO_TEST_CASE(registering_incompatible_types_should_raise_a_static_assert_failure)
{
BOOST_CHECK_STATIC_ASSERT_FAILURE(IFoo< A* >().as< B* >());
}
我希望这个BOOST_CHECK编译良好并通过。但是,我希望用户代码在实际执行以下操作时编译失败:
void myAwesomeMethod()
{
auto result = IFoo< A* >().as< B* >();
...
}
知道吗?
仅供参考,编译时失败通常会阻止编译。。。这就是他们来这里的原因。
我可以想出两种方法来实现你的提议:
- 使用SFINAE
- 使用编译器特定的选项
SFINAE
从字面上看,SFINAE的意思是:替换失败不是错误。它适用于模板上下文,并允许从重载集中悄悄丢弃被证明不充分的函数。SFINAE的使用产生了概念检查的概念,并使用用于支持这些检查的特征对属性进行分类。
在您的情况下,这意味着如果您可以以某种方式将要测试的表达式放在SFINAE可能应用的上下文中,那么您可以尝试检测特定函数是否已被有效丢弃。
例如:
#include <iostream>
#include <utility>
struct Foo {};
struct Bar {};
template <typename T>
auto foo(T t) -> decltype(std::declval<Foo>() + t) { std::cout << "Tn"; }
void foo(...) { std::cout << "ellipsisn"; }
int main() { foo(Bar()); }
收益率:
ellipsis
(参见ideone),即使在任何地方都没有定义operator+(Foo, Bar)
。
不幸的是,这可能不适用于所有情况(还不确定),但它应该可以在所有兼容的编译器上移植。
编译器特定
另一种可能性是使用编译器特定的功能。编译器测试套件必须验证这些编译器是否正确诊断了错误,在您的情况下,当满足static_assert
条件时,确实会发出错误。因此,编译器可能对此有钩子。
例如,在Clang测试套件中,可以找到一个SemaCXX/static-assert.cpp
文件:
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
int f();
static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}}
static_assert(true, "true is not false");
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
void g() {
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
}
class C {
static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
};
template<int N> struct T {
static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}}
};
T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}}
T<2> t2;
template<typename T> struct S {
static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}}
};
S<char> s1; // expected-note {{in instantiation of template class 'S<char>' requested here}}
S<int> s2;
-fsyntax-only
避免代码生成,-verify
表示编译器检查指定的expected-note
、expected-warning
和expected-error
是否正确满足。
如果不是,则编译器将返回错误代码。当然,这可能是编译器特有的。
- Boost.TEST with CLion: "Test framework quit unexpectedly"
- 使用 C++ Boost.Test 组织单元测试?
- Boost.Test - 如何在交叉点上检查两个向量
- 在 Boost.Test 中异常时双倍释放
- 数据集(和样本)何时在 boost::test 中销毁?
- 抑制boost.test中的退出信号
- 静态链接再次链接boost.test和cmake在Windows上的mingw
- 我应该使用boost.test分别测试不同类别的类别
- Boost.Test 显示测试持续时间
- 在哪里可以找到Eclipse中解析的Boost.Test输出
- 在BOOST test中添加测试套件而不是测试用例
- GCC 地址清理器 - 将库功能列入黑名单(特别是 boost::test)
- Debugging Boost.Test in Eclipse:debugger 不会在断点处停止
- Boost.Test Custom Type using decorator boost::unit_test::tol
- Boost.Test 使用正则表达式测试文件内容
- 如何将Boost.Test输出记录到HRF中的stdout和XML中的文件中
- 为什么我不能在 Boost.Test 测试用例中创建线程?
- Boost.Test吐出垃圾,而不是可读的错误消息
- Boost.test cannot find main
- Boost Test Boost _CHECK_EQUAL,类型可转换为数组