জেনেরিক আর্গুমেন্ট হিসাবে একটি নির্দিষ্ট ধরণের সাথে এসটিএল ধারক


25

আমি কোনও ফাংশন তৈরি করতে পারি যা std::stringএকটি পরামিতি হিসাবে একটি নির্দিষ্ট ধরণের (বলতে দিন ) একটি ধারক গ্রহণ করে

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

এবং এটিকে ইনপুট হিসাবে স্টাইলের প্রতিটি ধরণের জন্য কল করবেন? উপরের মত?

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
@ থাইজিজব্রো হ্যাঁ এটি সাধারণভাবে একটি ভাল ধারণা। তবে আমি মনে করি যে ওপি কেবল নির্দিষ্ট ধরণের সাথে এটি ব্যবহার করতে চায় std::string, তাই ..
গানেরুয়ানিয়াও

3
পছন্দ করুন ওপি বলেছে যে এটি একটি নির্দিষ্ট ধরণের সাথে কাজ করা উচিত । অতএব এটি আর সাধারণকরণের কোনও লাভ নেই।
এম স্পিলার

1
@ বুদ্ধিমানবৃন্দ আপনার অর্থ কী বোঝাতে পেরেছি তা আমি বুঝতে পারি। আমি ওপির আসল অভিপ্রায় সম্পর্কে নিশ্চিত নই, তিনি কেবল বলেছিলেন একটি নির্দিষ্ট প্রকার চান; আপনার এটি ওপিকে ব্যাখ্যা করার দরকার হতে পারে। :)
গানিউয়ানিয়াও

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

@ গীতুয়ানিয়াওর উত্তরে যুক্ত করে আমি মনে করি আমরা এটিকে আরও সাধারণ করতে পারি:

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 :: স্ট্রিং ব্যবহার করছেন এবং আগামীকাল তিনি পরিবর্তে একটি মাই কাস্টমস্ট্রিং ব্যবহার করতে চান। কেবল এটিই কোনও এক জায়গায় কোড সম্পাদনা করতে হবে, তাই এটি বজায় রাখা সহজ হবে না?
বুদ্ধিমানব্রো

কিন্তু এই কিভাবে এটি সীমিত করতে দেখাবেন না পারেন এবং querent বিশেষভাবে "একটি ধারক নিয়ে যেতে চেয়েছিলেন - এসটিডি :: স্ট্রিং বা MyCustomString উপাদানের একটি নির্দিষ্ট ধরনের সঙ্গে "। যেমনটি, এটি কোনও টেম্পলেট বলে মনে হয় এমন কোনও ধরণের গ্রহণ করবে এবং তার পরিবর্তে এটি কেবল একটি একক <টাইপনেম সি> এ কেন টেমপ্লেট করবে না? এটি অনেক সহজ এবং সামান্য আরও সাধারণীকরণ - যেমন আপনার ধারক হিসাবে স্ট্যান্ড :: স্ট্রিং (ওরফে স্ট্যান্ড :: বেসিক_স্ট্রিং <char>) লাগবে তবে কাস্টম স্ট্রিং মাই কাস্টমস্ট্রিং নয়, সুতরাং এটি সম্পূর্ণ জেনেরিক নয়।
সাশা

এবং যদি ফাংশনটি উপাদানগুলি std :: স্ট্রিংয়ের প্রত্যাশা করে, ব্যবহারকারীদের একটি std :: tuple <int, two, std :: nullptr_t> পাস করার অনুমতি দেয় তবে এটি ব্যবহার করা এবং বজায় রাখা আরও শক্ত করে তোলে ।
সাশা

@ সাশা হুম। আমি আপনার পয়েন্ট দেখুন. সেটা সত্য. সতর্ক থাকুন জন্য ধন্যবাদ!
বুদ্ধিমানব্রো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.