C ++: тип параметра, который требует наследования от нескольких интерфейсоподобных классов - PullRequest
0 голосов
/ 31 августа 2018

Я хочу иметь возможность создавать не шаблонную функцию, которая требует, чтобы тип класса был унаследован от нескольких других классов.

Нечто подобное

class A1
{};

class A2
{};

class A3
{};

class B: public A1, public A2, public A3
{};

class C: public A1, public A3
{};

void Foo(const C&)
{}

int main(void)
{
    B b;
    C c;

    Foo(b); // error. But B inherited from A1 and A3, so I want to be able pass it
    Foo(c); // ok

    return 0;
}

Буду рад услышать любые предложения по решению проблемы.

Примечание: некоторые языки, такие как Swift и Objective-C, имеют эту функцию как часть языка, называющего «соответствующие протоколы»

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Определите новый интерфейс I, который является производным от A1 и A3 (но не реализует ни одну из его чисто виртуальных функций), и заставьте Foo принять const I&. Классы, производные от I, должны будут переопределять чистые виртуальные объекты как в A1, так и в A3.

0 голосов
/ 31 августа 2018

Если вы ослабляете (устраняете) требование не-шаблонности, это делается через SFINAE, например:

template<class T>
typename std::enable_if<
        std::is_base_of<A1, T>::value
        && std::is_base_of<A3, T>::value>::type
    Foo(T const &);

В противном случае вам понадобится больше хитростей, а точнее, вам все равно понадобится шаблонное решение, хотя шаблоны должны быть изолированы в другом месте. Одним из возможных решений, кратко изложенных, было бы что-то вроде:

struct A1 {};
struct A2 {};

struct B: A1, A2 {};
struct C: A1, A2 {};

template<class B1, class B2> struct product {
    template<class T> product(T &t): b1(t), b2(t) {}
    operator B1 &() const { return b1; }
    operator B2 &() const { return b2; }
private:
    B1 &b1;
    B2 &b2;
};

void f(product<A1, A2> p) {}

int main() {
    B b;
    C c;
    f(b);
    f(c);
}

(Для краткости я ограничил количество оснований двумя - вы можете фактически расширить этот многовариантный адаптер для произвольной упаковки - и оставив в стороне конструкцию из временных объектов - все еще не ракетостроение.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...