2016-06-22 26 views
5

Sto cercando di estendere una classe base con alcuni membri dati e quindi ho bisogno di alcuni argomenti aggiuntivi del costruttore oltre agli argomenti del costruttore che la mia classe base ha bisogno. Voglio inoltrare i primi argomenti del costruttore alla classe base. Ecco quello che ho provato:Come posso derivare e aggiungere nuovi argomenti alla versione di base del costruttore?

#include <string> 
#include <utility> 

struct X 
{ 
    X(int i_) : i(i_) {} 
    int i; 
}; 

struct Y : X 
{ 
    template <typename ...Ts>  // note: candidate constructor not viable: 
    Y(Ts&&...args, std::string s_) // requires single argument 's_', but 2 arguments 
//^        // were provided 
    : X(std::forward<Ts>(args)...) 
    , s(std::move(s_)) 
    {} 

    std::string s; 
}; 

int main() 
{ 
    Y y(1, ""); // error: no matching constructor for initialization of 'Y' 
// ^~~~~~ 
} 

Tuttavia, il compilatore (clang 3.8, C++ 14 modalità) sputa i seguenti messaggi di errore di me (i messaggi principali sono anche nel codice sorgente sopra per la lettura di convenienza):

main.cpp:23:7: error: no matching constructor for initialization of 'Y' 
    Y y(1, ""); 
    ^~~~~~ 
main.cpp:13:5: note: candidate constructor not viable: requires single argument 's_', but 2 arguments were provided 
    Y(Ts&&...args, std::string s_) 
    ^
main.cpp:10:8: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided 
struct Y : X 
    ^
main.cpp:10:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided 
1 error generated. 

Perché il clang sta cercando di dirmi che il mio costruttore di modelli ha solo un argomento, anche se il numero di argomenti è variadico? Come posso risolvere questo?

+0

è possibile aggiungere il parametro sull'inizio del costruttore? 'Ts && ...' nella parte anteriore dell'elenco dei parametri funzione/costruttore è un contesto non dedotto ... –

+0

@ W.F. Perché non si tratta di un contesto di deduzione del modello? Quando può essere dedotto? –

+0

@ W.F. Sì, compila, quando inserisco gli argomenti addizionali prima del pacchetto di argomenti 'Ts && ...'. Ma mi piacerebbe che arrivassero dopo il pacchetto. –

risposta

3

Ecco una possibile soluzione:

#include <string> 
#include <utility> 
#include<functional> 
#include<tuple> 
#include<iostream> 

struct X 
{ 
    X(int i_) : i(i_) {} 
    int i; 
}; 

struct Y : X 
{ 
    template<std::size_t... I, typename... A> 
    Y(std::integer_sequence<std::size_t, I...>, std::tuple<A...> &&a) 
     : X(std::get<I>(a)...), 
      s(std::move(std::get<sizeof...(I)>(a))) 
    { } 

    template <typename ...Ts> 
    Y(Ts&&...args) 
     : Y{std::make_index_sequence<sizeof...(Ts)-1>(), 
      std::forward_as_tuple(std::forward<Ts>(args)...)} 
    { } 

    std::string s; 
}; 

int main() 
{ 
    Y y(1, "foo"); 
    std::cout << y.s << std::endl; 
} 
+0

Non copiare la mia soluzione! :) –

+0

A proposito, non ci dovrebbero essere 'std :: tuple {std :: forward (args) ...}}' nella riga 24? –

+0

Questo è un po 'quello che sospettavo. Mi sembra di funzionare, ma è tutto ma ovvio dal codice cosa sta succedendo. –

3

È necessario spostare varargs alla fine dell'elenco degli argomenti.

#include <string> 
#include <utility> 

struct X 
{ 
    X(int i_) : i(i_) {} 
    int i; 
}; 

struct Y : X 
{ 
    template <typename ...Ts>   
    Y(std::string s_, Ts&&...args)  // <==== like this 
    : X(std::forward<Ts>(args)...) 
    , s(std::move(s_)) 
    {} 

    std::string s; 
}; 

int main() 
{ 
    Y y("", 1); 
} 
Problemi correlati