2016-06-22 17 views
5

Próbuję rozszerzyć klasę bazową o niektóre elementy danych i dlatego potrzebuję dodatkowych argumentów konstruktora oprócz argumentów konstruktora, których moja klasa bazowa potrzebuje. Chcę przekazać pierwsze argumenty konstruktora do klasy bazowej. Oto, co starałem:Jak wyprowadzić i dodać nowe argumenty do podstawowej wersji konstruktora?

#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' 
// ^~~~~~ 
} 

Jednak kompilator (dzyń 3.8, C++ 14 Tryb) pluje następujące komunikaty o błędach na mnie (główne komunikaty są również w powyższym kodzie źródłowym do czytania wygodę):

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. 

Dlaczego clang próbuje mi powiedzieć, że mój szablonowy konstruktor ma tylko jeden argument, mimo że liczba argumentów jest variadic? Jak mogę to rozwiązać?

+0

można dodać parametr na początku konstruktora? 'Ts && ...' na początku listy parametrów funkcji/konstruktora nie jest wydedukowanym kontekstem ... –

+0

@ W.F. Dlaczego nie jest to kontekst dedukcji szablonu? Kiedy można to wydedukować? –

+0

@ W.F. Tak, kompiluje się, kiedy umieszczam dodatkowe argumenty przed pakietem argumentów "Ts && ...". Ale chciałbym, żeby przyszli po plecaku. –

Odpowiedz

3

Oto możliwe rozwiązanie:

#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

Nie kopiuj mojego rozwiązania! :) –

+0

Przy okazji nie powinno być 'std :: tuple {std :: forward (args) ...}}' w linii 24? –

+0

To było coś, co podejrzewałem. Wydaje mi się, że działam, ale z kodu tego, co się dzieje, wynika jasno. –

3

Musisz przenieść varargs na koniec listy argumentów.

#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); 
} 
Powiązane problemy