एसटीएल कंटेनर जेनेरिक तर्क के रूप में एक विशिष्ट प्रकार के साथ


25

क्या कोई ऐसा तरीका है जिससे मैं एक फ़ंक्शन बना सकता हूं जो एक विशिष्ट प्रकार के साथ एक कंटेनर लेता है ( std::stringएक पैरामीटर के रूप में कहता है )

void foo(const std::container<std::string> &cont)
{
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

और इनपुट के रूप में हर प्रकार के stl कंटेनर के लिए कॉल करें? ऊपर की तरह?

std::set<std::string> strset;
std::vector<std::string> strvec;
std::list<std::string> strlist;

foo(strset);
foo(strvec);
foo(strlist);

2
हां, इसे टेम्प्लेट फ़ंक्शन कहा जाता है। ;)
उलरिच एकहार्ट

2
अक्सर एक जोड़ी पुनरावृत्तियों को पास करना बेहतर माना जाता है (क्रमशः शुरुआत और कंटेनर के अंत-अतीत का प्रतिनिधित्व करते हुए)। जब तक पुनरावृत्तियाँ फ़ंक्शन की आवश्यकताओं को पूरा करती हैं, तब तक यह (अक्सर, कुछ अपवाद हैं) कोई फर्क नहीं पड़ता कि उन्हें किस प्रकार के कंटेनर से प्राप्त किया गया था।
पीटर

जवाबों:


21

आप कंटेनर प्रकार के लिए टेम्पलेट टेम्पलेट पैरामीटरfoo लेने के लिए एक फ़ंक्शन टेम्पलेट बना सकते हैं ।

जैसे

template<template<typename...> typename C>
void foo(const C<std::string> &cont)
{
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

लाइव


मुझे लगता है कि हम इसे और भी सामान्य कर सकते हैं। मेरा जवाब देखिए।
द वाइजब्रो

लार्स का जवाब बेहतर है क्योंकि यह सी-स्टाइल सरणियों के साथ भी काम करता है।
अयक्सन

1
@theLiveBro हाँ यह सामान्य रूप से एक अच्छा विचार है। लेकिन मुझे लगता है कि ओपी बस इसे विशिष्ट प्रकार के साथ उपयोग करना चाहता है std::string, इसलिए ..
गीतयुयनाओ

3
@theWebroro बिल्कुल ओपी ने कहा कि इसे एक विशिष्ट प्रकार के साथ काम करना चाहिए । इसलिए आगे इसे सामान्य करने का कोई लाभ नहीं है।
एम। स्पिलर

1
@theWebro मैं समझता हूं कि आपका क्या मतलब है। मुझे ओपी के मूल इरादे पर यकीन नहीं है, उन्होंने कहा कि एक विशिष्ट प्रकार चाहते हैं; आपको इसे ओपी को समझाने की आवश्यकता हो सकती है। :)
गीतुयनाओ

6

निर्भर करता है कि आप fooअन्य मामलों के लिए ओवरलोड करना चाहते हैं या नहीं

// Doesn't participate in overload resolution when not applicable
template<typename Container, typename = std::enable_if_t<std::is_same_v<typename Container::value_type, std::string>>>
void foo(const Container &cont) {
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

// simpler
template<typename Container>
void foo(const Container &cont) {
   static_assert(std::is_same_v<typename Container::value_type, std::string>, "Container must contain std::string")
   for(std::string val: cont) {
      std::cout << val << std::endl;
   }
}

आप एक अलग परीक्षण का उपयोग कर सकते करने के लिए std::is_same, इस तरह के रूप std::is_convertibleअनुमति देने के लिए

std::vector<char *> c_strings;
foo(c_strings);

0

आप इसके बजाय पुनरावृत्तियों का उपयोग करने पर विचार कर सकते हैं। एक मध्यवर्ती परिणाम की तरह लग सकता है

template<typename Iter>
void foo(Iter begin, Iter end) {
  using T = decltype(*begin);
  std::for_each(begin, end, [] (cons T & t) {
    std::out << t << '\n';
  }
}

अब एक कॉल करने योग्य टेम्पलेट का उपयोग कर:

template<typename Iter, typename Callable>
void foo(Iter begin, Iter end, Callable & c) {
  std::for_each(begin, end, c);
}

हमने अभी उपयोग करने के लिए सीखा कि एसटीएल पहले से ही क्या प्रदान करता है।


-1

@ Songyuanyao के उत्तर को जोड़ते हुए, मुझे लगता है कि हम इसे और सामान्य कर सकते हैं:

template<template<typename...> typename C, typename ... D>
void foo(const C<D...> &cont)
{
   for(const auto& val: cont) {
      std::cout << val << std::endl;
   }
}

1
यह तत्व प्रकार को std :: string तक सीमित नहीं करता है, इसलिए यह प्रश्न का उत्तर नहीं देता है।
साशा

@ साशा यह सच है कि यह std :: string के लिए निश्चित नहीं है, लेकिन यह अधिक सामान्यीकृत है। ओपी एक विशिष्ट प्रकार का उपयोग करना चाहता है। आज कहो वह std :: string का उपयोग कर रहा है और कल वह इसके बजाय एक MyCustomString का उपयोग करना चाहता है। क्या इसे बनाए रखना आसान नहीं होगा क्योंकि उसे केवल एक ही स्थान पर कोड को संपादित करना है?
द वाइजब्रो

लेकिन यह नहीं दिखाता है कि इसे या तो std :: string या MyCustomString तत्वों तक कैसे सीमित किया जाए - और विशेष रूप से " एक विशिष्ट प्रकार के साथ एक कंटेनर" लेना चाहते थे । जैसा कि, यह किसी भी प्रकार को स्वीकार करता है जो कि एक टेम्प्लेट होता है, और उस बिंदु पर इसके बजाय केवल एक ही <टाइपनेम सी> पर टेम्पलेट क्यों नहीं? यह बहुत सरल और थोड़ा अधिक सामान्यीकृत है - जैसे कि आपका std :: string (aka std :: basic_string <char>) कंटेनर के रूप में होगा, लेकिन कस्टम संरचना MyCustomString नहीं, इसलिए यह पूरी तरह से सामान्य नहीं है।
साशा

और समारोह की उम्मीद करता है, तो तत्व std जा करने के लिए :: स्ट्रिंग, उन पारित करने के लिए अनुमति देता है एक std :: टपल <int, डबल, std :: nullptr_t> यह बनाता है कठिन का उपयोग करें और बनाए रखने के लिए।
साशा

@ साशा हम्म। में तुम्हारी बात समझ रहा हूँ। यह सच है। सर उठाने के लिए धन्यवाद!
द वंडरब्रो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.