2015-03-15 8 views
6

std::back_insert_iteratorvalue_typevoid के बराबर है से कंटेनर की VALUE_TYPE को निकालने के लिए, लेकिन यह भी एक protected सदस्य container कि अंतर्निहित Container के लिए सूचक रखती है। मैं, कंटेनर की value_type को निकालने के लिए एक लक्षण वर्ग लिखने के लिए कोशिश कर रहा हूँ इन पंक्तियों के साथ:लक्षण वर्ग एक back_insert_iterator

#include <iterator> 
#include <type_traits> 
#include <vector> 

template<class OutputIt> 
struct outit_vt 
: 
    OutputIt 
{ 
    using self_type = outit_vt<OutputIt>; 
    using value_type = typename std::remove_pointer_t<decltype(std::declval<self_type>().container)>::value_type; 
}; 

int main() 
{ 
    std::vector<int> v; 
    auto it = std::back_inserter(v); 
    static_assert(std::is_same<outit_vt<decltype(it)>::value_type, int>::value, ""); 
} 

Live Example

बहरहाल, यह (कम या ज्यादा प्रत्याशित) अधूरा प्रकार त्रुटियों में चलाता है। क्या कंटेनर value_type निकालने के लिए वैसे भी है?

+0

आप नेस्टेटर से प्राप्त घोंसला वाले प्रकार का उपयोग क्यों नहीं करते? [लाइव उदाहरण] (http://coliru.stacked-crooked.com/a/3547c063ddfb1ddb) – dyp

+0

@dyp मैं डाफ्ट था, 'back_insert_iterator' में नेस्टेड टाइपपीफ' कंटेनर_टाइप' भी – TemplateRex

+0

हाल ही में जोड़ा गया लाइव उदाहरण देखें। - ओहह कि एक सार्वजनिक सदस्य है। मुझे लगता है कि – dyp

उत्तर

6

@Rapptz द्वारा जवाब सही लेकिन सामान्य कोड के लिए (यानी है जब यह स्पष्ट एक प्रायोरी नहीं है एक साथ एक सौदों कि क्या कच्चे T* या back_insert_iterator या मानक लाइब्रेरी के अन्य आउटपुट इटरेटर में से एक), एक और व्यवस्थित दृष्टिकोण आवश्यक है।

उस प्रभाव के लिए, उपयोगकर्ता द्वारा परिभाषित namespace xstd में कक्षा टेम्पलेट output_iterator_traits की परिभाषा के नीचे।

#include <iterator>    // iterator, iterator_traits, input_iterator_tag, output_iterator_tag, random_access_iterator_tag 
           // back_insert_iterator, front_insert_iterator, insert_iterator, ostream_iterator, ostreambuf_iterator 
#include <memory>    // raw_storage_iterator 

namespace xstd { 

template<class T> 
struct output_iterator_traits 
: 
     std::iterator_traits<T> 
{}; 

template< class OutputIt, class T> 
struct output_iterator_traits<std::raw_storage_iterator<OutputIt, T>> 
: 
     std::iterator<std::output_iterator_tag, T> 
{}; 

template<class Container> 
struct output_iterator_traits<std::back_insert_iterator<Container>> 
: 
     std::iterator<std::output_iterator_tag, typename Container::value_type> 
{}; 

template<class Container> 
struct output_iterator_traits<std::front_insert_iterator<Container>> 
: 
     std::iterator<std::output_iterator_tag, typename Container::value_type> 
{}; 

template<class Container> 
struct output_iterator_traits<std::insert_iterator<Container>> 
: 
     std::iterator<std::output_iterator_tag, typename Container::value_type> 
{}; 

template <class T, class charT = char, class traits = std::char_traits<charT>> 
struct output_iterator_traits<std::ostream_iterator<T, charT, traits>> 
: 
     std::iterator<std::output_iterator_tag, T> 
{}; 

template <class charT, class traits = std::char_traits<charT>> 
struct output_iterator_traits<std::ostreambuf_iterator<charT, traits>> 
: 
     std::iterator<std::output_iterator_tag, charT> 
{}; 

} // namespace xstd 

unspecialized संस्करण बस std::iterator_traits<T> से विरासत है, लेकिन 6 उत्पादन iterators <iterator> और <memory> हेडर में परिभाषित के लिए, विशेषज्ञताओं std::iterator<std::output_iterator_tag, V> जहां V प्रकार इटरेटर के operator=(const V&) का एक तर्क के रूप में प्रदर्शित है से विरासत।

डालने iterators के लिए, यह T को typename Container::value_type से मेल खाती है, कच्चे भंडारण iterators के लिए, और क्रमशः T और charT, को ostream और ostreambuf iterators के लिए।

रूप

template<class InputIt, class OutputIt> 
auto my_fancy_algorithm(InputIt first, InputIt last, OutputIt dest) 
{ 
    using T = typename xstd::output_iterator_traits<OutputIt>::value_type; 
    for (; first != last; ++first) { 
     // ... construct arguments from *first 
     *dest++ = T{ /* arguments */ }; 
    } 
} 

तो transparantly दोनों कच्चे संकेत और मानक लाइब्रेरी की उत्पादन iterators के साथ काम करेंगे की एक सामान्य एल्गोरिथ्म।

2

तुम बस container_type इस्तेमाल कर सकते हैं यह है कि:

#include <iterator> 
#include <type_traits> 
#include <vector> 

template<typename T> 
struct outit_v { 
    using container_type = typename T::container_type; 
    using value_type = typename container_type::value_type; 
}; 

int main() 
{ 
    std::vector<int> v; 
    auto it = std::back_inserter(v); 
    static_assert(std::is_same<outit_v<decltype(it)>::value_type, int>::value, ""); 
} 

Live Example

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