2011-05-17 45 views
9

में एक प्रकार की स्थिति मैं सी ++ 0x को आज़मा रहा हूं और मैं सोच रहा था कि आने वाली निम्न समस्या को कैसे हल किया जाए। मैं एक variadic टेम्पलेट वर्ग मिल गया है:एक भिन्नता टेम्पलेट पैरामीटर पैक

template<typename... T> 
class MyLovelyClass { 

template<typename SomeType> 
void DoSthWithStorageOfSomeType(); 

private: 
    std::tuple<std::vector<T>...> m_storage; 
}; 

समारोह वहाँ m_storage टपल कि SomeType टेम्पलेट तर्क से मेल खाती है में वेक्टर पर हेरफेर किसी प्रकार का कर (या अगर यह नहीं करता है समय असफल संकलन के लिए लगता है टी)। यह कैसे कर सकता है?

मेरा विचार पैरामीटर पैक में कुछ टाइप का सूचकांक ढूंढना था और फिर उचित वेक्टर प्राप्त करने के लिए std :: प्राप्त करें, लेकिन मुझे नहीं पता कि पहले भाग को कैसे करना है।

+0

सी ++ 14, और इस तरह कुछ मानक पुस्तकालय कार्यान्वयन प्रदान 'std :: मिल <एसटीडी: : वेक्टर > (m_storage) '। आपको जांचना चाहिए और देखना चाहिए कि आपके पास यह सुविधा है या नहीं, चीजों को बहुत आसान बनाता है। –

उत्तर

7

यहां कुछ प्रकार के कोड हैं जो इसे पहले प्रकार यू के लिए एक टुपल की रैखिक खोज करने के लिए करते हैं, और अगर यह यू नहीं मिल पाता है तो संकलन-समय त्रुटि देता है। नोट अगर टुपल में एकाधिक यू है तो यह केवल पहले पाता है एक। सुनिश्चित नहीं है कि वह नीति है जिसे आप चाहते हैं या नहीं। यह संकलन-समय सूचकांक को पहले यू के टुपल में लौटाता है। शायद आप इसे अपने std::get में इंडेक्स के रूप में उपयोग कर सकते हैं।

अस्वीकरण: इस उत्तर के लिए एक साथ फेंक दिया गया। केवल हल्के ढंग से परीक्षण किया। एक खाली ट्यूपल जैसे एज मामलों में एक ग़लत त्रुटि संदेश होता है जिसे बेहतर किया जा सकता है। आदि

#include <type_traits> 
#include <tuple> 

template <class Tuple, class T, std::size_t Index = 0> 
struct find_first; 

template <std::size_t Index, bool Valid> 
struct find_first_final_test 
    : public std::integral_constant<std::size_t, Index> 
{ 
}; 

template <std::size_t Index> 
struct find_first_final_test<Index, false> 
{ 
    static_assert(Index == -1, "Type not found in find_first"); 
}; 

template <class Head, class T, std::size_t Index> 
struct find_first<std::tuple<Head>, T, Index> 
    : public find_first_final_test<Index, std::is_same<Head, T>::value> 
{ 
}; 

template <class Head, class ...Rest, class T, std::size_t Index> 
struct find_first<std::tuple<Head, Rest...>, T, Index> 
    : public std::conditional<std::is_same<Head, T>::value, 
        std::integral_constant<std::size_t, Index>, 
        find_first<std::tuple<Rest...>, T, Index+1>>::type 
{ 
}; 

#include <iostream> 

int main() 
{ 
    typedef std::tuple<char, int, short> T; 
    std::cout << find_first<T, double>::value << '\n'; 
} 
+0

धन्यवाद - मुझे यह पसंद है! क्या मैं दो चीजों का सुझाव दे सकता हूं: 1) अतिरिक्त त्रुटि से बचने के लिए std :: integral_constant से झूठी स्थिति में विरासत जोड़ना :: मूल्य नहीं मिला है। 2) खाली ट्यूपल टेम्पलेट के लिए विशेषज्ञता जोड़ना <कक्षा टी, std :: size_t अनुक्रमणिका> संरचना find_first , टी, इंडेक्स> : सार्वजनिक find_first_final_test <अनुक्रमणिका, झूठी> { }; –

+1

मेरी आशा यह है कि आप इस कोड का उपयोग अपनी जरूरतों को ठीक करने के लिए नींव के रूप में करेंगे, जैसे कि आपके दो सुझाव जोड़ना। इसके साथ भागो! :-) –

+0

ठीक है। धन्यवाद :) –

1

सी ++ 14 समाधान:

template <typename T, typename U=void, typename... Types> 
constexpr size_t index() { 
    return std::is_same<T, U>::value ? 0 : 1 + index<T, Types...>(); 
} 

उपयोग:

cout << index<A, Args...>() << "\n"; 
+0

या तो यह g ++ 5.4 पर segfaults जब प्रकार सूची में नहीं है (6 की कोशिश नहीं की है)। –

0

मैं, "प्रकार नहीं मिला" Elazar के समाधान के लिए मामले के लिए समर्थन जोड़ा SIZE_MAX वापस लौट कर:

template <class T, class F = void, class ...R> 
constexpr size_t TypeIndex() { 
    return is_same<T,F>::value 
     ? 0 
     : is_same<F,void>::value || TypeIndex<T,R...>() == SIZE_MAX 
     ? SIZE_MAX 
     : TypeIndex<T,R...>() + 1; 
} 

संपादित करें: मैंने इसका उपयोग करने के लिए स्विच किया पैरामीटर पैक का आकार "नहीं मिला" सूचकांक मान के रूप में। यह सूचकांक या इटरेटर एक "पिछले अंत एक" की एसटीएल उपयोग की तरह है और एक अधिक सुरुचिपूर्ण समाधान बनाता है:

template <class T, class F = void, class ...R> 
constexpr size_t TypeIndex() { 
    return is_same<T,F>::value || is_same<F,void>::value ? 0 : TypeIndex<T,R...>() + 1; 
} 
संबंधित मुद्दे