我有一个使用T某些函数的模板类template<typename T> Foo。然而,事实证明,即使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。
发布于 2014-03-06 09:09:00
为了要求类型是具有某些可访问成员函数的类类型,只需引用它们。例如,在Foo的每个构造函数中,您可以这样说
Foo()
{
(void) sizeof( decltype( t.foo() ) );
(void) sizeof( decltype( t.bar() ) );
}上面的代码比您的示例所需的要多一点,但是它向您展示了如何轻松地确保这些函数可以使用某些参数调用,或者具有某些签名。
或者,您可以将这样的表达式放入static_assert中。
发布于 2014-03-06 09:14:32
类似于@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设计的概念相关,所以这样的测试在未来可能会更方便。
发布于 2014-03-06 10:21:16
以您的代码为例,我将简单地使用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();
}https://stackoverflow.com/questions/22212740
复制相似问题