2013-03-22 11 views
7

के माध्यम से एक इटरेटर के मूल्य की घोषणा करने के लिए सी ++ 98, मैं आम तौर पर एक इटरेटर का मान प्रकार में एक चर घोषित करने के लिए निम्नलिखित का उपयोग करें:कैसे decltype

typename std::iterator_traits<Iterator>::value_type value; 

सी ++ 11 में हम decltype है और मैं मान प्रकार निकालना सबसे आसान तरीका सोचा था है:

decltype(*iterator) value; 
दुर्भाग्य से सबसे iterators के लिए

, * के इटरेटर प्रकार VALUE_TYPE & और VALUE_TYPE नहीं है। प्रकार के संशोधन वर्गों के बिना, किसी भी विचार, उपरोक्त मालिश करने के लिए value_type (और कोई संदर्भ नहीं) में मालिश करने के लिए कैसे?


मुझे नहीं लगता कि प्रश्न अनुचित है क्योंकि निम्नलिखित काफी मजबूत है लेकिन एक और चर बनाने के लिए समाप्त होता है।

auto x = *iterator; 
decltype(x) value; 

भी ध्यान रखें कि मैं वास्तव में deduced प्रकार चाहते हैं और न सिर्फ एक उदाहरण उदा अगर मैं इन मूल्यों के std :: वेक्टर घोषित करना चाहता था।

+0

अभिव्यक्ति के प्रकार का उपयोग किया था '* iterator' है' std :: iterator_traits :: reference', नहीं 'value_type'। यह आवश्यक नहीं है 'value_type & ', और' decltype' अभिव्यक्ति के प्रकार की रिपोर्ट अलग-अलग रूप से इसकी मूल्य श्रेणी के आधार पर रिपोर्ट कर सकता है। –

+0

यदि आप * बस * अपने संपादन की दो पंक्तियों को जोड़ना चाहते हैं, तो समतुल्य 'typename std :: क्षय :: प्रकार मान;', लेकिन नीचे दिए गए उत्तर को देखें और केवल ' यह मत करो :) मैं इसे सिर्फ ['std :: decay'] के रूप में जोड़ रहा हूं (http://en.cppreference.com/w/cpp/types/decay) इस क्यू/ए में पहले उल्लेख नहीं किया गया था। –

उत्तर

15

iterator_traits का उपयोग जारी रखें। decltype(*iterator)*iter = something अभिव्यक्ति में विशेष चीजें करने के लिए कुछ प्रकार की अजीब प्रॉक्सी कक्षा भी हो सकती है।

उदाहरण: MSVC 2012 को

#include <iostream> 
#include <iterator> 
#include <typeinfo> 
#include <vector> 

template <typename T> 
void print_type() 
{ 
    std::cout << typeid(T).name() << std::endl; 
} 

template <typename Iterator> 
void test(Iterator iter) 
{ 
    typedef typename 
     std::iterator_traits<Iterator>::value_type iter_traits_value; 

    auto x = *iter; 
    typedef decltype(x) custom_value; 

    print_type<iter_traits_value>(); 
    print_type<custom_value>(); 
} 

int main() 
{ 
    std::vector<int> a; 
    std::vector<bool> b; 

    test(a.begin()); 
    test(b.begin()); 
} 

आउटपुट:

int
int
bool
class std::_Vb_reference<struct std::_Wrap_alloc<class std::allocator<unsigned int>>>

वे समान नहीं हैं।

+0

लेकिन जैसा कि मैंने अपने संपादन में उल्लेख किया है, निम्न कार्य करता है: auto x = * iterator; decltype (एक्स) मूल्य; –

+3

@GlenLow: आपने "काम" को परिभाषित नहीं किया है। उत्तर में मेरा संपादन देखें (aschepler, कृपया संपादित करें)। @ GManNickG के संपादन के लिए – GManNickG

+1

+1। ; -] – ildjarn

1

इस उपयोग के लिए मुझे std :: decay पसंद है। Typicall मैं

std::vector<int> vec; 
using value_type = typename std::decay< decltype(*begin(vec)) >::type; 
static_assert(std::is_same< int, value_type >::value, "expected int"); 
+0

सुझाव के लिए धन्यवाद, यह काम करता है (और मैंने कुछ नया सीखा है!) लेकिन यह 'std :: iterator_traits :: value_type' से कम वर्बोज़ नहीं है जब मेरे पास पहले से ही इटरेटर का प्रकार है। –

+0

सच। iterator_traits <> जाने का रास्ता हैं। मैं वास्तव में अपने सुझाव का अधिक उपयोग कर रहा हूं जब मेरे पास है, उदाहरण के लिए, एक अज्ञात कंटेनर प्रकार। अगर आपके पास पहले से ही इटेटरेटर प्रकार है, तो आप निश्चित रूप से सही हैं। –

+0

मुझे ध्यान रखना चाहिए कि यह अभिव्यक्ति काम नहीं कर सकती है जहां इटरेटर का संदर्भ प्रकार कुछ विकृत प्रॉक्सी है, जैसा कि 'std :: vector ' ऊपर उल्लिखित विशेषज्ञता है। –

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