2016-06-22 10 views
5

Bazı sınıf üyeleriyle bir temel sınıfı genişletmeye çalışıyorum ve bu nedenle temel sınıfımın ihtiyaç duyduğu yapıcı argümanlarına ek olarak bazı ek kurucu argümanlarına ihtiyacım var. İlk kurucu argümanlarını temel sınıfa iletmek istiyorum. İşte denedim budur: AncakKurucunun temel sürümüne nasıl yeni argümanlar türer ve eklerim?

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

, derleyici (çınlama 3.8, C++ 14 mod) bana aşağıdaki hata iletilerini tükürür (ana mesajlar kolaylık okumak için yukarıdaki kaynak kodunda da):

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. 

Neden argüman sayısı değişkendir olsa da, templu kurucumun yalnızca bir argümanı olduğunu söylemeye çalışan clang neden söylemektedir? Bunu Nasıl Çözebilirim?

+0

Eğer yapıcı başında üzerinde parametresini ekleyebilirsiniz: Burada

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

+0

@ W.F. Neden şablon kesinti bağlamı değil? Ne zaman çıkarılabilir? –

+0

@ W.F. Evet, ek argümanları "Ts && ..." argüman paketinden önce koyduğumda derler. Ama paketin peşine düşmek istiyorum. –

cevap

3

olası bir çözüm mü? `Ts && ...` işlev/yapıcı parametre listesinin ön tarafında çıkar çıkmaz bağlam ...
+0

Çözümümü kopyalamayın! :) –

+0

Bu arada, std :: tuple {std :: ileri (args) ...}} '24 satırında olmamalıdır? –

+0

Şüphelendiğim şey bu. Çalışıyorum gibi görünüyor, ama olanlardan ne olduğu belli oluyor. –

3

Varargs öğesini argümanlar listesinin sonuna taşımak zorundasınız.

#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; 
} 
İlgili konular