2012-12-20 11 views
22

मुझे क्षमा करें अगर इसे पहले से ही उत्तर दिया गया है, क्योंकि मुझे यह नहीं मिला ...एक वेक्टर में एक भिन्न तर्क सूची डालने?

असल में मेरे पास एक ऑब्जेक्ट है जिसे इसके कन्स्ट्रक्टर में एक भिन्न तर्क सूची लेने और वेक्टर में तर्क संग्रहीत करने की आवश्यकता है। मैं एक वेक्टर को एक वैरिएडिक कन्स्ट्रक्टर के तर्कों से कैसे शुरू करूं?

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

आपके उदाहरण में कुछ अमान्य वाक्यविन्यास है। आप क्या पूछने की कोशिश कर रहे हैं? –

+8

'std :: startizer_list <जेनेरिक नोड *>' का उपयोग करें। –

+0

क्षमा करें। स्पष्टीकरण के लिए, मैं std :: वेक्टर को पॉप्युलेट करने के लिए तर्क सूची का उपयोग कैसे करूं? @MooingDuck, मैं std :: startizer_list में देखूंगा। धन्यवाद। – fredbaba

उत्तर

22

सबसे अच्छा बात एक का उपयोग किया जाएगा प्रारंभकर्ता सूची

#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 

क्या आपके पास पहले से करीबी, सी ++ 11 का उपयोग वेक्टर के initializer_list उपयोग करने के लिए है:

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

और यहां कोई सी ++ 11 संस्करण नहीं है जिसमें कोई प्रारंभकर्ता_लिस्ट नहीं है। यह बदसूरत और जटिल है, और कई कंपाइलरों से गायब सुविधाओं की आवश्यकता है। प्रारंभकर्ता सूची

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 

सबकुछ से संबंधित नहीं, मुझे नहीं पता कि वे पॉइंटर्स के स्वामी हैं या नहीं। यदि वे हैं, तो इसके बजाय std::unique_ptr का उपयोग करें।

+0

'टेम्पलेट जेनेरिक नोड (टी * ... इनपुट) नहीं होगा: inputs_ {inputs ...} {} 'वह क्या हो पहले से है? मैं अभी भी 'std :: startizer_list <जेनेरिक नोड *>' 'के साथ जाऊंगा। –

+0

@ जोनाथन वाकई: कोई विचार नहीं कि मैंने कभी ऐसा क्यों नहीं सोचा। फिक्स्ड। –

+0

@MooingDuck, अन्य: धन्यवाद। मुझे जिस चीज की जरूरत थी। – fredbaba

1

आप जब तक यह एक टेम्पलेट है एक variadic तर्क सूची का उपयोग नहीं कर सकते हैं, आप, के रूप में कहा गया है, इस तरह की एक initializer_list उपयोग कर सकते हैं:

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

आपके पास सहायक कार्य क्यों है? –

+0

@MooingDuck बस वैरिएडिक टेम्पलेट पैरामीटर का उपयोग दिखाने के लिए –

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

इसका कारण यह है कि आप केवल इस तरह के एक समारोह तर्क सूची या प्रारंभकर्ता-सूची के रूप में कुछ संदर्भों में एक बयान के रूप में एक पैरामीटर पैक का विस्तार नहीं कर सकते, काम नहीं करता।

इसके अलावा आपका कन्स्ट्रक्टर हस्ताक्षर गलत है, यदि आप एक भिन्न टेम्पलेट लिखने की कोशिश कर रहे हैं तो इसे टेम्पलेट होने की आवश्यकता है!

एक बार जब आप लिखना अपने निर्माता हस्ताक्षर सही ढंग से जवाब आसान है, बस पैक विस्तार के साथ वेक्टर का निर्माण:

#include <vector> 

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

(आप के बजाय यह निर्माता शरीर में के साथ सेट किया जा सकता था:

inputs_ = { inputs... }; 

लेकिन अच्छे बच्चे सदस्य प्रारंभकर्ताओं का उपयोग कन्स्ट्रक्टर बॉडी में असाइनमेंट नहीं करते हैं।)

इस समाधान का नकारात्मक हिस्सा यह है कि टेम्पलेट निर्माण या किसी भी प्रकार के पॉइंटर तर्क स्वीकार करता है, लेकिन यदि वे GenericNode* पर परिवर्तनीय नहीं हैं तो वेक्टर बनाने की कोशिश करते समय एक त्रुटि देगी। आप टेम्पलेट को केवल GenericNode पॉइंटर्स स्वीकार करने के लिए बाध्य कर सकते हैं, लेकिन यह तब होता है जब आप अन्य उत्तरों का सुझाव देते हैं और निर्माता को std::initializer_list<GenericNode*> लेते हैं, और फिर आपको किसी भी बदसूरत enable_if SFINAE चाल की आवश्यकता नहीं है।

1

एक और तरीका है यह करने के लिए: सी ++ 11 सत्य से

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

उदाहरण पर्याप्त ... सरल लग रहा है;) नहीं एक पूर्ण समाधान है, लेकिन आप कुछ विचार दे सकता है।

+0

यह आपके 'बी 1' और' बी 2' उदाहरणों के लिए ठीक काम करता है, लेकिन ओपी 'ब्लॉब बी 3 {"सर्किल", "त्रिकोण", "स्क्वायर"} करना चाहता है;' और आपका 'ब्लॉब' कन्स्ट्रक्टर ऐसा नहीं कर सकता , क्योंकि आप '_v' के लिए मान-प्रारंभिकरण का उपयोग करते हैं। यदि आप इसे '_v' के लिए सूची-प्रारंभिकरण का उपयोग करने के लिए बदलते हैं तो यह समर्थन करेगा कि ओपी क्या करना चाहता है। –

संबंधित मुद्दे