2017-02-03 8 views
6

मेरे पास एक ऐसा कार्य है जिसे मैं सामान्य बनाना चाहता हूं। सीधे शब्दों में कहें, मैं एक std::string s है कि मैं एक पार्सर पैदा करने के लिए एक std::vector<std::string> (यह "1, 2, 3" में के रूप में एक सूची है) के साथ की प्रक्रिया है, और समारोह एक std::vector<T> लौटना चाहिए, Tdouble या int तक ही सीमित है।युगल/इनट्स टेम्पलेट फ़ंक्शन का वेक्टर

वेक्टर में परिवर्तित मूल्य होना चाहिए।

मैं std::transform के अंतिम पैरामीटर के साथ अटक कर रहा हूँ, के रूप में यह std::stod और std::stoi के बीच स्विच करना चाहिए। जिस समाधान का मैं खोज रहा हूं वह टेम्पलेट मेटाप्रोग्रामिंग जादू है, if (std::is_same<T,int>::value) के साथ नहीं।

कोई संकेत?

template <class T> 
auto get_vector(std::string s) -> std::vector<T> 
{ 
    std::vector<T> v; 

    auto tmp = split(s); 

    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), ??); 

    return v; 
} 
+0

'डबल' के लिए एक विशेषज्ञता जोड़ें? – alain

उत्तर

5

एक बात तुम कर सकते हो एक stringstream और एक lambda उपयोग और stringstream आप के लिए रूपांतरण है।

std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), 
    [](const std::string& elem) -> T 
    { 
     std::stringstream ss(elem); 
     T value; 
     ss >> value; 
     return value; 
    }); 
+4

केवल यह करें यदि डेटा की मात्रा बहुत छोटी है तो आपको परवाह नहीं है कि यह हास्यास्पद रूप से धीमा है या नहीं। –

3

istream_iterator का उपयोग करते हुए की तरह कुछ:

template <class T> 
auto get_vector(std::string s) -> std::vector<T> { 
    std::vector<T> v; 
    std::istringstream iss(s); 
    std::copy(std::istream_iterator<T>(iss), std::istream_iterator<T>(), std::back_inserter(v)); 
    return v; 
} 
7

समारोह टेम्पलेट विशेषज्ञता के माध्यम से std::stoi और std::stod को भेजने:

template <typename T> 
auto parse_number(std::string const& s) -> T; 

template <> 
auto parse_number<int>(std::string const& s) -> int 
{ 
    return std::stoi(s); 
} 

template <> 
auto parse_number<double>(std::string const& s) -> double 
{ 
    return std::stod(s); 
} 

template <class T> 
auto get_vector(std::string const& s) -> std::vector<T> 
{ 
    std::vector<T> v; 
    auto tmp = split(s); 
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), &parse_number<T>); 
    return v; 
} 
+0

यह उत्तर है। संक्षेप में, ओपी को 'some_lexical_caster (const std :: string &)' कॉल करने की आवश्यकता है। असल में आप बूस्ट के उपयोग का भी उपयोग कर सकते हैं यदि इसे कभी भी अधिक सामान्य समाधान की आवश्यकता होती है। लेकिन, यहां हमारे उद्देश्यों के लिए, यह 'parse_number' ठीक है। –

+1

एएसएच का जवाब दिलचस्प है, और यह मुझे विशेषज्ञता से बचने की अनुमति देता है। क्या कोई कमी है? – senseiwa

+0

@ सेंसईवा हां, 'std :: stringstream' बहुत धीमा हो सकता है। यह वास्तव में आपके 'विभाजन' की दक्षता पर निर्भर करता है। –

-2

एक कोशिश पकड़ ब्लॉक में तर्क encasing की कोशिश करो।

try { 
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), std::stoi); 
} catch (const std::invalid_argument) { 
    std::transform(tmp.begin(), tmp.end(), std::back_inserter(v), std::stod); 
} 

इसका सादगी का लाभ है और यह काफी तेज़ होगा।

+0

कुछ चीजों को ध्यान में रखना चाहिए: (1) अपवादों को रेफरी (2) द्वारा पकड़ा जाना चाहिए, हर किसी के पास अपवाद सक्षम नहीं हैं (3) यह अपेक्षित रूप से काम नहीं कर सकता है, क्योंकि 'int' को' डबल' 'पर लागू किया जा सकता है। (4) यदि आप स्ट्रिंग में डबल पास करते हैं तो 'std :: stoi' अपवाद नहीं फेंकता है, इसलिए आप कैच ब्लॉक को भी फेंक सकते हैं, इसे कभी भी निष्पादित नहीं किया जाएगा। – Rakete1111

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