2012-07-13 9 views
6

मैं कुछ इस तरह करना चाहते हैं:मैं एक वैरिएडिक प्रकार पैक से एक विशिष्ट प्रकार कैसे प्राप्त करूं?

template<typename ...T> struct foo 
{ 
    bar<0 /*to index through types in pack*/ ,T...>::type var1; 
    bar<1 /*to index through types in pack*/ ,T...>::type var2; 
    ... 
} 

लेकिन मैं bar कैसे परिभाषित करेंगे? ऐसा करने के लिए कोई रिकर्सन तकनीक नहीं आती है।

मुझे एक सामान्य तकनीक चाहिए ताकि मैं किसी विशेष प्रकार को टाइप पैक से टाइप कर सकूं, न केवल उदाहरण में दिखाए गए दो।

+0

क्या आप var1 और var2 चाहते हैं होने के लिए के रूप में यदि sizeof ... (टी) == 0 या sizeof ... (टी) == 1 ? – Andrzej

+3

क्यों न केवल 'std :: tuple ' का उपयोग करें? 'Std :: के रूप में तत्वों को एक्सेस करें (tup) 'और' std :: tuple_element > :: type' के रूप में टाइप करें। – Xeo

+0

@Xeo आप सही हैं लेकिन मैं विभिन्न टेम्पलेट्स के साथ काम करने के लिए मूल तकनीक सीखना चाहता हूं। मुझे उम्मीद है कि आप समझेंगे। – M3taSpl0it

उत्तर

5
#include <iostream> 
#include <typeinfo> 

template<class T, class T2, class... Args> 
class C 
{ 
public: 
    typedef T type1; 
    typedef T2 type2; 
}; 

int main() 
{ 
    typedef C<int, double, int, float> c; 
    std::cout << typeid(c::type1).name() << " " << typeid(c::type2).name() << std::endl; 
} 

या एमबी ऐसा कुछ।

#include <iostream> 
#include <typeinfo> 

template<int N, class T, class... Args> 
struct expand 
{ 
public: 
    typedef typename expand<N - 1, Args...>::type type; 
}; 

template<class T, class... Args> 
struct expand<1, T, Args...> 
{ 
public: 
    typedef T type; 
}; 

template<class... Args> 
class argsExpander 
{ 
public: 
    typedef typename expand<1, Args...>::type type1; 
    typedef typename expand<2, Args...>::type type2; 
}; 

template<class... Args> 
class C 
{ 
public: 
    typename argsExpander<Args...>::type1 var1; 
    typename argsExpander<Args...>::type2 var2; 
}; 

int main() 
{ 
    C<int, double, int, float> c; 
    std::cout << typeid(c.var1).name() << " " << typeid(c.var2).name() << std::endl; 
} 

http://liveworkspace.org/code/7de289f128e86eb6006f576cbaf98991

+0

मुझे लगता है कि सवाल का तात्पर्य है कि 'typedef'-section स्वचालित रूप से –

+2

होना चाहिए कि 'विस्तार' मुहावरे बहुत चालाक है। – tenfour

+0

@refp कोड अपडेट किया गया है। – ForEveR

1

हाँ, तो आप इस प्रत्यावर्तन के साथ वास्तव में क्या कर सकते हैं ... आप कर रहे हैं और अधिक या कम फिर से लागू करने std::tuple (और परोक्ष std::get)।

कड़ी मेहनत सदस्यों तक पहुंचने में आती है, क्योंकि आप उन्हें var1, var2 आदि नहीं कह सकते हैं, जब तक कि आप उन्हें मैन्युअल रूप से नाम दे रहे हों।

template <typename... TypeList> struct foo; 

template <typename Head, typename... Tail> 
struct foo<Head, Tail...>: public foo<Tail...> 
{ 
    Head var; 
}; 

मैं यहाँ विरासत का उपयोग किया है, लेकिन संरचना (एक foo<Tail...> tail सदस्य का उपयोग) के रूप में अच्छी तरह से काम करता है।

अब, अगर आपके प्रकार अद्वितीय हैं, आप प्रकार के आधार पर सदस्य का उपयोग कर सकते हैं ...

// this overload if VarType is the first 
template <typename VarType, typename... FooTail> 
VarType& foo_get(foo<VarType, FooTail...>& f) 
{ 
    return f.var; 
} 

// this overload to walk down to foo's parent 
template <typename VarType, typename FooHead, typename... FooTail> 
VarType& foo_get(foo<FooHead, FooTail...>& foo) 
{ 
    return foo_get<VarType>(static_cast<foo<FooTail...>>(f)); 
} 

// call like: 
// int &x = foo_get<int>(my_foo_object); 

या आप स्थिति तक पहुंच सकते हैं:

template <int N, typename... TypeList> struct GetHelper; 

template <typename Head, typename... Tail> 
struct GetHelper<0, Head, Tail...> 
{ 
    static Head& get(foo<Head, Tail...> &f) { return f.var; } 
}; 

template <int N, typename Head, typename... Tail> 
struct GetHelper<N, Head, Tail...>: public GetHelper<N-1, Tail...> 
{}; 

template <int N, typename... TypeList> 
auto foo_get(foo<TypeList...> &f) 
    -> GetHelper<N, TypeList...>::get(*static_cast<foo<TypeList...>*>(0)) 
{ 
    return GetHelper<N, TypeList...>::get(f) 
} 

// call like: 
// int &x = foo_get<2>(my_foo_object); 

उन दोनों के लिए सुधार किया जा सकता बेहतर त्रुटि रिपोर्टिंग प्राप्त करें (और हालांकि मैंने दोनों तकनीकों का उपयोग किया है, मैंने इस नमूना कोड को संकलित करने की भी कोशिश नहीं की है)

+2

'std :: tuple' को पुन: कार्यान्वित करने के बजाय, ओपी को इसका उपयोग करना चाहिए। – Xeo

+0

मैं सहमत हूं, लेकिन चूंकि ओपी ने उस समाधान को पसंद किया जो कि प्रश्न से मेल नहीं खाता था, मुझे यकीन नहीं है कि मैं सब के बाद प्रश्न समझता हूं। – Useless

1

यदि मैं आपका प्रश्न सही ढंग से समझता हूं, तो आप कुछ समान टी लागू करना चाहते हैं ओ std :: टपल:

मुझे लगता है कि टपल इस तरह से कार्यान्वित किया जाता है:

template <class T> 
class tuple 
{ 
    T mem; 
}; 

template <class T, class... REST> 
class tuple : tuple<REST...> 
{ 
    T mem; 
}; 
1

सीधे शब्दों में उपयोग std :: @Xeo रूप टपल टिप्पणी रखता है। यह सुविधाजनक है और वही करता है जो आप करने का प्रयास करते हैं।

उद्धरण:

क्यों नहीं सिर्फ एक std::tuple<T...> का उपयोग करें?

std::get<I>(tup) के रूप में पहुँच तत्वों और

प्रकार std::tuple_element<I, std::tuple<T...>>::type