在Java中,参数实现多个接口的是possible to declare。您必须使用泛型语法,但您可以:
public <T extends Appendable & Closeable> void spew(T t) {
t.append("Bleah!\n");
if (timeToClose())
t.close();
}
在C ++中,常见的模式是使用仅包含纯虚函数的类作为接口:
class IAppendable {
public:
virtual void append(const std::string&) = 0;
};
class ICloseable {
public:
virtual void close() = 0;
};
编写一个带ICloseable
的函数(这只是多态)是微不足道的:
void closeThis(ICloseable&);
但是带有参数的函数的签名是什么,如在Java示例中那样,继承自 ICloseable
和 {{1} }?
答案 0 :(得分:5)
以下是使用标准设施编写的方法:
template <class T>
std::enable_if_t<
std::is_base_of<IAppendable, T>{} && std::is_base_of<ICloseable, T>{},
void
> closeThis(T &t) {
t.append("end");
t.close();
}
如果有更多的基类,我建议制作一个更简洁的类型特征,在enable_if
中检查它们:
constexpr bool allTrue() {
return true;
}
template <class... Bools>
constexpr bool allTrue(bool b1, Bools... bools) {
return b1 && allTrue(bools...);
}
template <class T, class... Bases>
struct all_bases {
static constexpr bool value = allTrue(std::is_base_of<Bases, T>{}...);
constexpr operator bool () const {
return value;
}
};
template <class T>
std::enable_if_t<
all_bases<T, IAppendable, ICloseable>{},
void
> closeThis(T &t) {
t.append("end");
t.close();
}
答案 1 :(得分:1)
@ Quentin的优秀答案促使我编写了一个通用的,可变的inherits
模板。它允许您轻松指定任意数量的基类。
#include <type_traits>
template<class... T> struct inherits :
std::true_type
{};
template<class T, class Base1, class... Bases>
struct inherits<T, Base1, Bases...> :
std::conditional_t< std::is_base_of<Base1, T>{},
inherits<T, Bases...>,
std::false_type
>
{};
第一个模板参数是要检查的类型,其余参数是第一个类型必须继承的类型。
例如,
class A {};
class B {};
class C {};
template<class T>
std::enable_if_t<
inherits<T, A, B, C>{},
void
> foo(const T& t)
{
// ...
}
此处,无论将T
作为参数传递给foo
,都必须从A
,B
和C
继承。