Passando variadic modelli di classe sottoclassi di funzione che accetta solo la classe di base (tramite il parametro pacchetto detrazione / deduzione)

StackOverflow https://stackoverflow.com/questions/3671145

Domanda

** ho ottenuto un paio di suggerimenti per rendere la mia pura funzione generica, che avrebbe funzionato, ma preferirei che limita la funzione di accettare solo Base e dei suoi figli.

Hai problemi a effettuare una funzione che può accettare gli argomenti di un tipo di base di classe template variadic, mentre la funzione sarà effettivamente chiamato con classi che derivano dalla base. Ho provato un paio di cose. Ecco l'idea generale. Dato:

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

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

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

Qual è il modo corretto per creare una funzione che fa questo:

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;
}

Output:

foobar'd

Ho provato alcune variazioni della funzione moosh_together, nessuno dei quali lavoro. Lasciando come sopra genera un errore di compilazione di perdere argomenti template. Sono sicuri di come passare attraverso la funzione gli argomenti di template che definiscono DerivedA e DerivedB.

Altre cose che ho provato (metodo di fucile da caccia):

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
È stato utile?

Soluzione

Modifica

Se avete bisogno di entrambi i pacchetti dei parametri, si può semplicemente mettere sia nella specifica template:

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);
}

Questo funziona perché il parametro confezioni sono dedotte da argomenti e non specificati in un elenco. Naturalmente non si può avere una classe che dipende da molteplici pacchetti di parametri.

Altri suggerimenti

Quando si scrive: string moosh_together(Base A, Base B), chiedetevi cosa Base è. Base è un classe template , non è un tipo di classe.

In altre parole, data:

template <typename T>
struct foo {};

foo<int> e foo<float> sono due tipi completamente diversi, che così è accaduto per essere fatto dallo stesso modello di classe. Non hanno classe base comune, e non è possibile fare riferimento a loro semplicemente come foo più di quanto è possibile fare riferimento sia int e float con un solo tipo.

Si potrebbe scomporre le parti non dipendenti di Base:

struct Core
{
    string name;
};

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

E quindi fare riferimento alle porzioni Core:

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

O semplicemente rendere la funzione del tutto generico:

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

E dice "se avete i membri necessari, è possibile utilizzare questa funzione".

Non potreste creare una classe base nella gerarchia di ereditarietà per Base e passare che alla funzione moosh_together()? (Low conoscenza di C ++ qui)

Credo che l'espansione generale di questo è

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);
}

Questo potrebbe essere scritto come segue

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...);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top