扩展两个类的参数的语法

时间:2015-06-23 21:51:24

标签: c++ inheritance

在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} }?

2 个答案:

答案 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();
}

Live on Coliru

如果有更多的基类,我建议制作一个更简洁的类型特征,在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,都必须从ABC继承。

Live on Coliru