我需要一种简单的方法来在模板内断言模板参数实现了一个方法(或其父类之一)。我读过概念检查库,但很难找到一个简单的例子来做像这样的简单检查。
我尝试关注其他帖子(比如这个和另一个),我已经对其进行了修改,因此我可以使其适用于许多方法类型(在我的示例中 Foo (methodName) 和 has_foo (Checker name) 将,一次正常工作,被包装为宏参数,因此它可以用于任何方法)
我目前拥有的代码是这个:
template <typename TypeToBeChecked, typename Sign>
class has_foo {
static_assert( false , "inside root declaration of " "has_foo" );
public:
static const bool result = false;
};
template <typename TypeToBeChecked , typename R>
class has_foo < TypeToBeChecked , R(void) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(void)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U> static no deduce(U*, Helper<R (BaseMixin::*)(), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template <typename TypeToBeChecked , typename R , typename ARG1>
class has_foo< TypeToBeChecked , R(ARG1) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(ARG1)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(ARG1){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t> class Helper{};
template <typename U>
static no deduce(U*, Helper<R (BaseMixin::*)(ARG1), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template <typename TypeToBeChecked , typename R , typename ARG1 , typename ARG2>
class has_foo< TypeToBeChecked , R(ARG1, ARG2) >
{
static_assert( false , "inside specialization of " "has_foo" " for R(ARG1 , ARG2)" );
class yes { char m;};
class no { yes m[2];};
struct BaseMixin { R Foo(ARG1,ARG2){} };
struct Base : public TypeToBeChecked, public BaseMixin {};
template <typename T, T t>
class Helper{};
template <typename U>
static no deduce(U*, Helper<R (BaseMixin::*)(ARG1,ARG2), &U::Foo>* = 0);
static yes deduce(...);
public:
static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
};
template< typename Type >
struct Connector
{
static_assert( has_foo< Type , int(int, double) >::result , "Type has no Foo method" );
void Operate() {
Type t;
t.Foo(3);
}
};
struct Bla1 { int Foo(double f) { return (int)f; } };
struct Bla2 { int Foo(int g, double h) { return g+(int)h;} };
int main()
{
//Connector< Bla1 > a;
Connector< Bla2 > b;
};
当我编译这个示例代码时(g++ 4.4.3 ubuntu 带有 -std=c++0x 选项,所以 static_assert 被识别)我得到这个:
$ g++ test.cpp -std=c++0x -o test
test.cpp:72: error: static assertion failed: "inside root declaration of has_foo"
test.cpp:79: error: static assertion failed: "inside specialization of has_foo for R(void)"
test.cpp:93: error: static assertion failed: "inside specialization of has_foo for R(ARG1)"
test.cpp:108: error: static assertion failed: "inside specialization of has_foo for R(ARG1 , ARG2)"
就在那儿等一下,(注意 Connector< Bla1 > a 已被评论)我的第一个问题是:
1)我是否正确假设如果正在评估断言,则正在实例化包含模板?
编辑:由 GMan 回答:在解析期间评估 static_assert,而不是在实例化模板时评估。用 sizeof(TypeToBeChecked)==0 替换 false 使其绑定到编译时
2)我是否正确假设由于连接器模板类中的静态断言正在实例化带有 int(int, double) 签名的 has_foo,那么不应实例化单参数和无参数的特化?我的假设有什么问题?
编辑:这个假设是正确的,但现在我根据 1) 的答案进行了修复,实例化过程现在按预期运行
3)如果我取消注释 Connector< Bla1 > 一行,我希望它会失败(因为 Bla1 只有一个带有单个参数签名的 Foo 。但事实并非如此。知道可能出了什么问题吗?特别考虑到第一个链接的帖子