2016-11-18 5 views
6

मेरे पास कई कार्यों है कि बहुत समान हैं, लेकिन अलग संख्या और स्थानीय वस्तुओं के प्रकार के साथ चलाएँ:स्थानीय चर के परिवर्तनीय संख्या बनाने के लिए विविधता टेम्पलेट पैरामीटर के माध्यम से पुनरावृत्ति कैसे करें?

template <class T> T* create1(const std::vector<std::string>& names) 
{ 
    A a(names[0]); 
    B b(names[1]); 
    C c(names[2]); 

    if (a.valid() && b.valid() && c.valid()) 
     return new T(a, b, c); 
    else 
     return NULL; 
} 

template <class T> T* create2(const std::vector<std::string>& names) 
{ 
    D d(names[0]); 
    E e(names[1]); 

    if (d.valid() && e.valid()) 
     return new T(d, e); 
    else 
     return NULL; 
} 

create1<ABC>({ "nameA", "nameB", "nameC" }); 
create2<DE>({ "nameD", "nameE" }); 

variadic टेम्पलेट मुझे इस रूप में उन कार्यों का एक रिफैक्टरिंग प्राप्त करने में मदद करेंगे?

template <class T, typename Args...> T* create() 
{ 
    // loop over Args and create 2 or 3 objects 
    // if (....valid()) 
    // return T(...); 
    // else 
    // return NULL; 
} 

create<ABC,A,B,C>({ "nameA", "nameB", "nameC" }); 
create<DE,D,E>({ "nameD", "nameE" }); 

कोई सफलता के साथ How can I iterate over a packed variadic template argument list? और iterating over variadic template's type parameters जांच की गई। यह नहीं देख सकता कि मैं विभिन्न प्रकार की स्थानीय वस्तुओं की एक चर संख्या कैसे बना सकता हूं ...

+0

क्या उन्हें * स्थानीय वस्तुओं के लिए * की आवश्यकता है? या अस्थायी हैं ठीक है? – Rakete1111

+0

यदि संभव हो तो मैं स्थानीय पसंद करूंगा, क्योंकि वास्तव में उनकी रचना विफल हो सकती है और फिर कार्य की प्रारंभिक वापसी की ओर ले जाती है। पोस्ट अपडेट किया गया। – jpo38

+0

आप वेक्टर नामों का आकार क्यों नहीं देखते हैं और यदि कोई कथन करते हैं? आप यह सब केवल एक समारोह में कर सकते हैं। यह विविध टेम्पलेट का उद्देश्य नहीं है। शायद आप [cstdarg] (http://www.cplusplus.com/reference/cstdarg/) का उपयोग करना चाहते हैं? – Stargateur

उत्तर

10

सबसे पहले, अपने नाम vector के रूप में न लें। उन्हें पैरामीटर पैक के रूप में ले जाएं। और, इसके अलावा, उनमें क्या आप वास्तव में चाहते हैं के एक पैकेट के रूप में लेते हैं:

bool is_valid() { return true; } 
template <class T, class... Ts> 
bool is_valid(T& arg, Ts&... args) { 
    return arg.valid() && is_valid(args...); 
} 

template <class T, class... Args> 
T* create(Args&&... args) { 
    if (is_valid(args...)) { 
     return new T{args...}; 
    } 
    else { 
     return nullptr; 
    } 
} 

और अब बस में सही काम पारित:

create<T>(A{"nameA"}, B{"nameB"}, C{"nameC"}); 
create<T>(D{"nameD"}, E{"nameE"}); 

, तो किसी कारण से, तुम सच में अलग करना चाहते हैं प्रकार और नाम, आप यह भी कर सकते हैं:

template <class T, class... Cs, class... As> 
T* create_classes(As&&... args) { 
    return create<T>(Cs{std::forward<As>(args)}...); 
} 
+0

असल में नहीं, मैंने शायद उदाहरण को बहुत सरल बना दिया है। संपादित पोस्ट देखें, मुझे कुछ और लचीला चाहिए। – jpo38

+0

मैं सी ++ 11 पर फंस गया हूं ... – jpo38

+0

आप 'create_classes' पर दो पैरामीटर पैक क्यों ले रहे हैं? – krzaq

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