我有一个模板类template<typename T> Foo
,它使用T
的某些功能。但是,事实证明,即使没有T
具有所有必需的成员函数,代码也可以编译。下面是一个例子。
template<class T>
struct Foo {
T t;
int foo() {
return t.foo();
}
int bar() {
return t.bar();
}
};
struct baz {
int foo() {
return 42;
}
};
int main() {
Foo<baz> x;
return x.foo();
}
如果T
没有提供所有必要的功能,我如何确保代码无法编译?我知道如果我使用包含所有继承并从中派生的基类,就可以做到这一点。但是,如果没有太多额外的代码,可以使用模板完成,我将非常感激。
我在Linux上使用gcc 4.8.2。
答案 0 :(得分:3)
为了要求类型是具有某些可访问成员函数的类类型,只需引用它们即可。例如。在Foo
的每个构造函数中,您可以说
Foo()
{
(void) sizeof( decltype( t.foo() ) );
(void) sizeof( decltype( t.bar() ) );
}
上面的内容比您的示例要多一些,但展示了如何轻松确保函数可以使用某些参数调用,或者具有某些签名。
或者您可以将这些表达式放在static_assert
。
答案 1 :(得分:2)
与@Cheers答案类似,但更通用(即使Foo
不包含T
也有效):
template<typename...>
struct test {};
template<typename T>
using Foo_test = test<
decltype(std::declval<T>().foo()),
decltype(std::declval<T>().bar())
>;
template<class T>
struct Foo : Foo_test<T> {
// ...
};
此问题与当前为C ++ 14设计的 concepts 有关,因此将来这些测试可能会更方便。
答案 2 :(得分:0)
使用您的代码,我只需使用static_assert
和std::is_member_function_pointer
,如下所示(文档here)
template<class T>
struct Foo {
static_assert(std::is_member_function_pointer<decltype(&T::foo)>::value, "");
static_assert(std::is_member_function_pointer<decltype(&T::bar)>::value, "");
T t;
int foo() {
return t.foo();
}
int bar() {
return t.bar();
}
};
struct baz {
int foo() {
return 42;
}
};
int main() {
Foo<baz> x;
return x.foo();
}