C++ 如何预期静态断言失败并使用Boost.Test框架处理它?

C++ 如何预期静态断言失败并使用Boost.Test框架处理它?,c++,unit-testing,c++11,boost-test,C++,Unit Testing,C++11,Boost Test,如果我有一个接受模板参数的方法,该模板参数应可转换为、base_或与返回的类型相同的类型,我该怎么做 例如,考虑这种方法: template <class T> class IFoo { public: template <class ServiceT> T* as() { static_assert(std::is_same< T, ServiceT >::value ||

如果我有一个接受模板参数的方法,该模板参数应可转换为、base_或与返回的类型相同的类型,我该怎么做

例如,考虑这种方法:

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");
        ...
    }
};
模板
类IFoo
{
公众:
模板
T*as()
{
静态断言(std::is_same::值
||std::是否可转换::值
||std::是::值的基础,
“IFoo::as()要求ServiceT是T的基础”);
...
}
};
现在,我想检查一下

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* >());
}
A类{};
B类{};
BOOST\u AUTO\u TEST\u案例(注册\u不兼容\u类型\u应\u引发\u静态\u断言\u失败)
{
BOOST\u CHECK\u STATIC\u ASSERT\u FAILURE(IFoo().as());
}
我希望这个BOOST_检查能够很好地编译并通过。但是,我希望用户代码在实际执行类似操作时编译失败:

void myAwesomeMethod()
{
    auto result = IFoo< A* >().as< B* >();

    ...
}
void myAwesomeMethod()
{
自动结果=IFoo()。作为();
...
}

有什么想法吗?

请参考,编译时失败通常会阻止编译。。。这就是他们来这里的原因

我可以想出两种方法来实现你的提议:

  • 使用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 << "T\n"; }

void foo(...) { std::cout << "ellipsis\n"; }

int main() { foo(Bar()); }
(请参阅)即使在任何地方都没有定义
运算符+(Foo,Bar)

不幸的是,这可能并不适用于所有情况(目前还不确定),但它应该可以移植到所有兼容的编译器上

特定于编译器的

另一种可能是使用特定于编译器的特性。编译器测试套件必须验证这些编译器是否正确诊断错误,并且在您的情况下,当满足
static\u 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;
//运行:%clang\u cc1-fsyntax only-验证%s-std=c++0x
int f();
静态断言(f(),“f”);//预期错误{static_assert expression不是整型常量表达式}
静态断言(true,“true不是false”);
静态断言(false,“false即false”);//预期错误{static_assert failed“false is false”}
void g(){
static_assert(false,“false是false”);//预期错误{{static_assert failed“false是false”}
}
C类{
static_assert(false,“false是false”);//预期错误{{static_assert failed“false是false”}
};
模板结构{
静态断言(N==2,“N不是2!”);//预期错误{{静态断言失败“N不是2!”}
};
T t1;//应为注释{{此处请求的模板类“T”的实例化中}
t2;
模板结构{
static_assert(sizeof(T)>sizeof(char),“类型不够大!”;//预期错误{{static_assert失败”类型不够大!}
};
S s1;//应为注释{{此处请求的模板类的实例化中}
s2;
-fsyntax only
避免代码生成和
-verify
表示编译器检查指定的
预期注释
预期警告
预期错误
是否正确满足


如果不是,编译器将返回一个错误代码。当然,这可能是特定于编译器的。

您是否尝试通过传递完全不相关的
Foo
参数来测试只接受
Bar
参数的函数。static_assert是一个编译时构造,因此您不需要测试该约束?@parapura-rajkumar,您是对的。单元测试—这只能证明它是类型安全的—我希望捕获静态断言失败,并将它们提升到api中的更高级别。我想得到一个尽可能接近开发代码的静态断言失败,这样编译错误就更相关了。@先生,你为什么不相信你的用户知道他们在某个时候写了什么?
// 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;