2012-12-20 14 views
22

Bir vektöre değişken bir argüman listesi eklemek mi istiyorsunuz? Bu zaten cevaplanmışsa ben bulamadım olarak

Temelde ben kurucusunda variadic argüman listesi alıp bir vektör içinde argümanları saklamak için gereken bir nesne var ... Bağışlayın. Bir vektörü, değişken bir yapıcının argümanlarından nasıl başlatabilirim?

class GenericNode { 
public: 
    GenericNode(GenericNode*... inputs) { 
      /* Something like... */ 
     // inputs_.push_back(inputs)...; 
} 
private: 
    std::vector<GenericNode*> inputs_; 
}; 
+1

Örneğinizde geçersiz bir sözdizimi var. Özellikle ne sormaya çalışıyorsun? –

+8

'std :: initializer_list ' işlevini kullanın. –

+0

Üzgünüm. Açıklığa kavuşturmak için, bir std :: vektörünü doldurmak için argüman listesini nasıl kullanırım? @MooingDuck, std :: initializer_list dosyasına bakacağım. Teşekkürler. – fredbaba

cevap

22

iyi şey olurdu başlatıcı listesi C++ 11 kullanılarak

#include <initializer_list> 
#include <vector> 
class GenericNode { 
public: 
    GenericNode(std::initializer_list<GenericNode*> inputs) 
     :inputs_(inputs) {} //well that's easy 
private: 
    std::vector<GenericNode*> inputs_; 
}; 
int main() { 
    GenericNode* ptr; 
    GenericNode node{ptr, ptr, ptr, ptr}; 
} //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c 

zaten ne kadar yakın, vektörün initializer_list kullanmaktır:

template<class ...Ts> 
    GenericNode(Ts... inputs) 
     :inputs_{inputs...} {} //well that's easy too 
    //compilation at http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae 

Ve burada hiç bir initializer_lists olmayan bir C++ 11 sürümü var. Çirkin ve karmaşıktır ve birçok derleyiciden eksik özellikler gerektirir. O sahip işaretçileri veya değilse her şeye

template<class T> 
using Alias = T; 

class GenericNode { 
public: 
    template<class ...Ts> 
    GenericNode(Ts... inputs) { //SFINAE might be appropriate 
     using ptr = GenericNode*; 
     Alias<char[]>{(//first part of magic unpacker 
      inputs_.push_back(ptr(inputs)) 
      ,'0')...,'0'}; //second part of magic unpacker 
    } 
private: 
    std::vector<GenericNode*> inputs_; 
}; 
int main() { 
    GenericNode* ptr; 
    GenericNode node(ptr, ptr, ptr, ptr); 
} //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9 
//thanks to R. Martinho Fernandes for helping me get it to compile 

İlgisiz başlatıcı listesini kullanın, ben bilmiyorum. Öyleyse, bunun yerine std::unique_ptr kullanın.

+0

Şablon GenericNode (T * ... girişleri): inputs_ {inputs ...} {} 'ne olduğunu zaten? yine de std :: initializer_list 'ile devam ediyorum. –

+0

@JonathanWakely: Neden hiç düşünmediğim hakkında bir fikrim yok. Sabit. –

+0

@MooingDuck, others: Teşekkürler. Tam ihtiyacım olan şey. – fredbaba

1
bir şablon olmadığı sürece, sen belirtildiği gibi, böyle bir initializer_list kullanabilirsiniz variadic argüman listesi kullanamazsınız

: Bir kullanmak

class GenericNode { 
public: 
    GenericNode(std::initializer_list<GenericNode*> inputs) : inputs_(inputs) 
    { 
    } 
private: 
    std::vector<GenericNode*> inputs_; 
}; 

template <class ... T> 
GenericNode* foo(T ... t) 
{ 
    return new GenericNode({t...}); 
} 
+0

Neden yardım işleviniz var? –

+0

@MooingDuck Sadece variadic şablon parametrelerinin kullanımını göstermek için –

4
// inputs_.push_back(inputs)...; 

sadece böyle bir fonksiyon argüman listesi veya başlatıcı-liste olarak belli bağlamlarda, bir ifadesi olarak bir parametre paketi genişletmek olamaz, çünkü bu işe yaramaz.

Ayrıca yapıcınızın imzası da yanlıştır, eğer değişken bir şablon yazmaya çalışıyorsanız, şablon olması gerekir!

Eğer yapıcı imza düzgün cevap kolaydır yazdıktan sonra sadece paket genişleme ile vektör yapılandırmak:

#include <vector> 

class GenericNode 
{ 
public: 
    template<typename... T> 
    GenericNode(T*... inputs) : inputs_{ inputs... } 
    { } 
private: 
    std::vector<GenericNode*> inputs_; 
}; 

(yerine ile yapıcı gövdesinde ayarlamak olabilirdi:

inputs_ = { inputs... }; 

ama havalı üye başlatıcıları yapıcı gövdesinde değil atama kullanır.)

bu çözümün dezavantajı olduğunu şablon yapı veya herhangi bir gösterici argümanı türünü kabul eder, ancak argümanlar GenericNode*'a dönüştürülemiyorsa, vektör oluşturmaya çalışırken bir hata verecektir. Yalnızca GenericNode işaretçiler kabul etmek şablonu sınırlamak olabilir, ancak diğer cevaplar önermek ne ve yapıcı bir std::initializer_list<GenericNode*> almak yaparsanız otomatik olarak böyle oluyor ve sonra herhangi bir çirkin enable_if SFINAE hileler gerekmez.

1

bir başka yolu bunu yapmak için:

#include <iostream> 
#include <vector> 

using std::vector; 

template <typename T> 
void variadic_vector_emplace(vector<T>&) {} 

template <typename T, typename First, typename... Args> 
void variadic_vector_emplace(vector<T>& v, First&& first, Args&&... args) 
{ 
    v.emplace_back(std::forward<First>(first)); 
    variadic_vector_emplace(v, std::forward<Args>(args)...); 
} 

struct my_struct 
{ 
    template <typename... Args> 
    my_struct(Args&&... args) 
    { 
     variadic_vector_emplace(_data, std::forward<Args>(args)...); 
    } 

    vector<int>& data() { return _data; } 

private: 
    vector<int> _data; 
}; 


int main() 
{ 
    my_struct my(5, 6, 7, 8); 

    for(int i : my.data()) 
     std::cout << i << std::endl; 
} 
1
class Blob 
{ 
    std::vector<std::string> _v; 
public: 

    template<typename... Args> 
    Blob(Args&&... args) 
    : _v(std::forward<Args>(args)...) 
    { } 

}; 

int main(void) 
{ 
    const char * shapes[3] = { "Circle", "Triangle", "Square" }; 

    Blob b1(5, "C++ Truths"); 
    Blob b2(shapes, shapes+3); 
} 

Örnek C++ 11 Gerçeğin yeterince ... basit görünüyor;) değil komple bir çözüm ama size bazı fikirler verebilir.

+0

Bu, 'b1' ve 'b2' örnekleriniz için işe yarıyor, ancak OP yapmak istiyor 'Blob b3 {" Daire "," Üçgen "," Kare "};' ve sizin 'Blob' yapıcınız bunu yapamaz Çünkü, _v' için değer sıfırlama kullanıyorsunuz. Eğer '_v' için liste başlatmayı kullanmak için değiştirirseniz, OP'nin ne yapmak istediğini destekleyecektir. –

İlgili konular