Передача подклассов шаблона класса Variadic в функцию, которая принимает только базовый класс (посредством вывода / вывода пакета параметров) - PullRequest
3 голосов
/ 08 сентября 2010

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

Возникли проблемы при создании функции, которая может принимать аргументы базового типа класса шаблонов с переменным числом аргументов, в то время как функция будет фактически вызываться с классами, производными от Base. Я попробовал несколько вещей. Вот общая идея. Дано:

template<typename... Args> struct Base {
    std::tuple<Args...> data;
    ... //other stuff
};

struct DerivedA : Base<string, int> {
};

struct DerviedB : Base<bool, string, int> {
};

Как правильно создать функцию, которая делает это:

string moosh_together(Base A, Base B) { //I only need access to Base's members
    return get<0>(A.data) + get<1>(B.data);
}

main() {
    DerivedA aThing;
        get<0>(aThing.data) = "foo";
    DerivedB bThing;
        get<1>(bThing.data) = "bar'd";
    cout << moosh_together(aThing, bThing) << endl;
}

Выход:

foobar'd

Я пробовал несколько вариантов функции moosh_together, ни одна из которых не работает. Если оставить это как выше, генерируется ошибка компилятора об отсутствующих аргументах шаблона. Я не уверен, как передать функции аргументы шаблона, которые определяют DerivedA и DerivedB.

Другие вещи, которые я пробовал (метод дробовика):

string moosh_together(Base<> A, Base<> B) {}
//err: conversion from 'DerivedA' to non-scalar type 'Base<>' requested

template<Base<typename... Args> T1, Base<typename... Args> T2>
string moosh_together(T1 A, T2 B) {}
//err: expected paramter pack before '...'

template<Base<Args...> T1, Base<Args...> T2>
string moosh_together(T1 A, T2 B) {}
//err: 'Args' was not declared in this scope

Ответы [ 4 ]

4 голосов
/ 08 сентября 2010

Изменить:

Если вам нужны оба пакета параметров, вы можете просто указать оба в спецификации шаблона:

template<typename... ArgsA, typename... ArgsB>
string moosh_together(const Base<ArgsA...>& A, const Base<ArgsB...>& B) {
    return get<0>(A.data) + get<1>(B.data);
}

Это работает, потому что пакеты параметров выводятся из аргументов и не указываются в списке. Естественно, у вас не может быть класса, который зависит от нескольких пакетов параметров.

2 голосов
/ 08 сентября 2010

Когда вы пишете: string moosh_together(Base A, Base B), спросите себя, что такое Base.Base - это шаблон класса , а не тип класса.

Другими словами, учитывая:

template <typename T>
struct foo {};

foo<int> и foo<float> - это два полностьюразличные типы, которые просто были сделаны из одного и того же шаблона класса.У них нет общего базового класса, и вы не можете ссылаться на них просто как foo больше, чем вы можете ссылаться как на int, так и float с одним типом.

Вы можете выделить независимые части Base:

struct Core
{
    string name;
};

template <typename... Args>
struct Base : Core
{
    // ...
};

А затем обратитесь к Core частям:

// pass by reference, to avoid unnecessary copying
string moosh_together(const Core& a, const Core& b);

Или просто сделайте функцию полностью универсальной:

template <typename BaseOne, typename BaseTwo>
string moosh_together(const BaseOne& a, const BaseTwo& b);

И скажите «если у вас есть необходимые участники, вы можете использовать эту функцию».

1 голос
/ 09 сентября 2010

Я думаю, что общее расширение это

string moosh_together(Base<T1...> A1, Base<T2...> A2, ... Base<Tn...> An) {
    return get<0>(A1.data) + get<1>(A2) + ... + get<n-1>(An.data);
}

Это можно записать следующим образом

template<int I> 
string moosh_together() { return ""; }

template<int I, typename ...Base1Ty, typename ... Bases>
string moosh_together(Base<Base1Ty...> const& base1, Bases const&... bases) {
    return get<I>(base1.data) + moosh_together<I+1>(bases...); 
}

template<typename ... Bases>
string moosh_together(Bases const&... bases) {
    return moosh_together<0>(bases...);
}
1 голос
/ 08 сентября 2010

Не могли бы вы создать базовый класс в иерархии наследования для Base и передать его в функцию moosh_together()?(Низкое знание c ++ здесь)

...