2014-12-20 10 views
8

निम्नलिखित कोड जो एक vector करने के लिए एक map रों कुंजी की नक़ल की संकलन करने की कोशिश में:मैं std :: ट्रांसफॉर्म में std :: <0> प्राप्त क्यों नहीं कर सकता?

map<string, string> mss; 
vector<string> vs; 

transform(mss.begin(), mss.end(), back_inserter(vs), get<0>); 

VS2013 भेद नहीं कर सकते जो get का इरादा है, लेकिन यह आसान उपयोग सिर्फ ठीक काम करता है:

vs.push_back(get<0>(*mss.begin())); 

get<0, string, string> निर्दिष्ट करने में मदद नहीं मिली। मैं क्या खो रहा हूँ?

उत्तर

8

std::get के कई ओवरलोड हैं, इसके अलावा, प्रत्येक एक फ़ंक्शन टेम्पलेट स्वयं है, इसलिए संकलक यह नहीं बता सकता कि आप कॉल साइट पर कौन सा चाहते हैं, जहां आप उनमें से किसी के पते के लिए अनुरोध करते हैं। आप std::get के प्रयोग पर जोर देते हैं, तो आप static_cast उपयोग करने की आवश्यकता होगी:

transform(mss.begin(), mss.end(), back_inserter(vs), 
      static_cast<const map<string, string>::key_type& 
         (*)(map<string, string>::value_type&)>(std::get<0>) 
        ); 

कौन सा static_cast में प्रकार के रूप में लंबे समय के रूप में काम करेगा या संभव समारोह टेम्पलेट की विशेषज्ञता तर्क के रूप में दिए गए की घोषणा से मेल खाता है। साथ ही, आप get<0, string, string> इत्यादि जैसे फ़ंक्शन टेम्पलेट्स के टेम्पलेट तर्कों को स्पष्ट रूप से निर्दिष्ट करने का प्रयास नहीं करते हैं - यह टेम्पलेट तर्क कटौती तंत्र के लिए है। न केवल वाक्यविन्यास बदसूरत है, लेकिन भविष्य में आपके संकलन को तोड़ने वाले अन्य अधिभार भी जोड़े जा सकते हैं।

transform(mss.begin(), mss.end(), back_inserter(vs), 
      [](map<string, string>::value_type& p){ return p.first; }); 

या एक सामान्य लैम्ब्डा अभिव्यक्ति (सी ++ 14):

एक ज्यादा बेहतर विकल्प एक लैम्ब्डा अभिव्यक्ति उपयोग करने के लिए है

transform(mss.begin(), mss.end(), back_inserter(vs), 
      [](auto& p){ return p.first; }); // or `return std::get<0>(p);` 

या std::mem_fn जो बांधता है इसके किसी डेटा सदस्य या सदस्य फ़ंक्शन को किसी दिए गए पॉइंटर पर तर्क:

#include <functional> 

transform(mss.begin(), mss.end(), back_inserter(vs), 
      mem_fn(&map<string, string>::value_type::first)); 
+1

धन्यवाद। मैं सुपर-संक्षिप्त '<0>' प्राप्त करने में सक्षम होने की उम्मीद कर रहा था, लेकिन ... इसका मतलब नहीं था। ओह अच्छा। – screwnut

5

मानचित्र में संग्रहीत जोड़ी का पहला सदस्य कॉन्स्टेक्टेड है। तो तकनीकी रूप से आप

get<0, const string, string> 

जरूरत है लेकिन वह, एक स्पष्ट अधिभार के लिए उम्मीदवारों की सूची को सीमित नहीं करता क्योंकि get कम से कम दो संस्करणों में उपलब्ध है: स्थिरांक संदर्भ तर्क के लिए और गैर स्थिरांक संदर्भ तर्क के लिए।

तुम एक डाली

const string &(*g)(const pair<const string, string> &) = 
    get<0, const string, string>; 

या

typedef map<string, string> Map; 

const Map::key_type &(*g)(const Map::value_type &) = 
    get<0, const Map::key_type, Map::mapped_type>; 

का उपयोग करके एक चुन सकते हैं और उसके बाद करना

transform(mss.begin(), mss.end(), back_inserter(vs), g); 
संबंधित मुद्दे