2015-06-23 3 views
3

В 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иIAppendable?

+1

вопрос: как реализовать класс, который inherets как из '' IAppendable' и ICloseable'? Или: как создать шаблонный класс/функцию/и т. Д. чей параметр 'typename T' должен игнорировать как' IAppendable', так и 'ICloseable'? – EyasSH

+0

Последний (я отредактировал для ясности). Реализация класса, реализующего оба, тривиальна: 'class A: public IAppendable, public ICloseable {};' – thirtythreeforty

ответ

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(); 
} 
+0

Интересно, спасибо! Использует ли SFINAE для возвращаемого типа единственный способ сделать это? (Я чувствую, что сообщение об ошибке не будет действительно связано с фактической ошибкой программиста.) – thirtythreeforty

+1

@thirtythreeforty Я думаю, что концепции, когда они, наконец, перейдут на язык, помогут определить более четкий синтаксис этих требований. На данный момент это идиоматический способ, отличный от перегрузок и всех. Разоблачение строки «Один» вызывает сообщение об ошибке, содержащее «кандидат: шаблон std :: enable_if_t {}, void> closeThis (T &)'. Не идеально, но не так плохо для ошибки шаблона;) – Quentin

+0

Я не уверен, что 'is_base_of' является правильной проверкой, так как он также обнаруживает двусмысленные и недоступные базы. (И, конечно, если мы используем шаблоны, я не понимаю, зачем нужны эти базовые классы вообще.) –

1

@ отличный ответ Квентина побудил меня написать обобщенный, VARIADIC 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.

Live on Coliru

+0

Хорошая реализация :) Кроме того, я манекен и пропустил мою копию-вставку функции 'allTrue' ... – Quentin

+0

Спасибо! Я думал, что вы оставили это как упражнение для читателя нарочно: D – thirtythreeforty

Смежные вопросы