টেমপ্লেটগুলিতে 'টাইপনেম' এবং 'শ্রেণি' কীওয়ার্ডের পার্থক্য?


504

টেমপ্লেটগুলির জন্য আমি উভয় ঘোষণা দেখেছি:

template < typename T >
template < class T >

পার্থক্য কি?

এবং নিম্নলিখিত কীওয়ার্ডগুলি (টেমপ্লেটগুলি সম্পর্কে জার্মান উইকিপিডিয়া নিবন্ধ থেকে নেওয়া) এর কীওয়ার্ডগুলির সঠিক অর্থ কী?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};

উত্তর:


430

typenameএবং classএকটি টেমপ্লেট নির্দিষ্ট করার প্রাথমিক ক্ষেত্রে বিনিময়যোগ্য:

template<class T>
class Foo
{
};

এবং

template<typename T>
class Foo
{
};

সমতুল্য

এই বলে যে, সেখানে নির্দিষ্ট ক্ষেত্রে রয়েছে যেখানে typenameএবং এর মধ্যে পার্থক্য রয়েছেclass

প্রথমটি নির্ভরশীল প্রকারের ক্ষেত্রে। typenameআপনি যখন নেস্টেড টাইপটিকে উল্লেখ করছেন যা অন্য টেমপ্লেট প্যারামিটারের উপর নির্ভর করে যেমন typedefএই উদাহরণটিতে:

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

দ্বিতীয়টি আপনি আসলে আপনার প্রশ্নে দেখান, যদিও আপনি এটি বুঝতে পারেন না:

template < template < typename, typename > class Container, typename Type >

কোনও টেম্পলেট টেমপ্লেট নির্দিষ্ট করার সময় , classকীওয়ার্ডটি উপরের হিসাবে ব্যবহার করা আবশ্যক - এটি এই ক্ষেত্রে এর সাথে বিনিময়যোগ্য নয় (দ্রষ্টব্য: যেহেতু C ++ 17 উভয় কীওয়ার্ডই এই ক্ষেত্রে অনুমোদিত)typename

classস্পষ্টভাবে কোনও টেম্পলেট ইনস্ট্যান্ট করার সময় আপনাকে অবশ্যই ব্যবহার করতে হবে :

template class Foo<int>;

আমি নিশ্চিত যে আমি মিস করেছি এমন অন্যান্য কেসগুলি রয়েছে তবে নীচের অংশটি হ'ল: এই দুটি মূলশব্দ সমতুল্য নয়, এবং এটি এমন কয়েকটি সাধারণ ক্ষেত্রে যেখানে আপনার একটি বা অন্য ব্যবহার করা দরকার।


45
শেষটি আসলে একটি বিশেষ ক্ষেত্রে এটি একটি শ্রেণীর সংজ্ঞা দেওয়ার জন্য আপনাকে অবশ্যই ক্লাস বা কাঠামো ব্যবহার করতে হবে, টাইপনেম নয়। স্পষ্টতই আপনার কোডের প্রথম দুটি বিটের template <typename T> typename Foo {};কোনওটিই প্রতিস্থাপন করা যায়নি , কারণ ফু <T> অবশ্যই একটি শ্রেণি।
স্টিভ জেসোপ

2
std::vector<int>::value_typeকোনও নির্ভরশীল প্রকার নয়, আপনার typenameসেখানে প্রয়োজন নেই - আপনার কেবলমাত্র এটির দরকার হয় যদি কোনও টাইপ কোনও টেম্পলেট প্যারামিটারের উপর নির্ভর করে, বলুনtemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
জর্জিট ফ্রিটস্কে

2
এবং আবারও, param_tনির্ভরশীল ধরণের নয়। নির্ভরশীল প্রকারগুলি হ'ল নামগুলি যা কোনও টেম্পলেট প্যারামিটারের উপর নির্ভরশীল , যেমন foo<param_t>::some_typeটেমপ্লেট প্যারামিটারগুলি নিজেরাই নয়।
জর্জি ফ্রিজচে

2
একটি সি ++ 1z প্রস্তাবনা N4051 আপনাকে ব্যবহার করার অনুমতি দেবে typename, যেমন template <typename> typename C
ব্যবহারকারী 4112979

4
হিসাবে GCC 5, জি ++ এখন একটি টেম্পলেট টেম্পলেট প্যারামিটারে টাইপনেমের অনুমতি দেয়
ন্নোসোস

95

নামকরণের জন্য টেমপ্লেট পরামিতি, typenameএবং classসমতুল্য। §14.1.2:

টেমপ্লেট-প্যারামিটারে ক্লাস এবং টাইপনেমের মধ্যে কোনও অর্থগত পার্থক্য নেই।

typenameযাইহোক টেমপ্লেটগুলি ব্যবহার করার সময় অন্য প্রসঙ্গে সম্ভব - সংকলকটিতে ইঙ্গিত দেওয়ার জন্য যে আপনি নির্ভরশীল ধরণের কথা উল্লেখ করছেন। §14.6.2:

কোনও নামটি টেম্পলেট ঘোষণার বা সংজ্ঞায় ব্যবহৃত হয় এবং এটি কোনও টেম্পলেট-প্যারামিটারের উপর নির্ভরশীল কোনও প্রকারের নাম না নেওয়াকে ধরে নেওয়া হয় যদি না প্রযোজ্য নাম অনুসন্ধানে কোনও প্রকারের নাম না পাওয়া যায় বা নামটি কীওয়ার্ড টাইপনেমের দ্বারা যোগ্য না হয়।

উদাহরণ:

typename some_template<T>::some_type

typenameসংকলক ব্যতীত আপনি সাধারণভাবে বলতে পারবেন না যে আপনি কোনও ধরণের উল্লেখ করছেন কিনা।


2
আমি নিয়মটি বুঝতে পারি, তবে সংস্থাপকটি ঠিক কোনও_পালিত <T> অভ্যন্তরীণভাবে টাইপ হিসাবে আচরণ করা থেকে বাধা দেয়? দুঃখিত যদি আমি স্পষ্ট কিছু মিস করছি।
batbrat

23

কোনও প্রযুক্তিগত পার্থক্য না থাকলেও আমি দুজনকে কিছুটা ভিন্ন জিনিস বোঝাতে ব্যবহার করতে দেখেছি।

একটি টেম্পলেটটির জন্য যা বিল্ট-ইনগুলি সহ কোনও ধরণের টি হিসাবে গ্রহণ করতে হবে (যেমন একটি অ্যারে)

template<typename T>
class Foo { ... }

একটি টেমপ্লেটের জন্য যা কেবলমাত্র টি যেখানে আসল শ্রেণি সেখানে কাজ করবে।

template<class T>
class Foo { ... }

তবে মনে রাখবেন যে এটি নিখুঁতভাবে একটি স্টাইলের জিনিস যা কিছু লোক ব্যবহার করে। মানক দ্বারা বাধ্যতামূলক বা সংকলক দ্বারা প্রয়োগ করা হয় না


15
আমি এটি উল্লেখ করার জন্য আপনাকে দোষ দিচ্ছি না, তবে আমি মনে করি যে এই নীতিটি বেশ বিপথগামী, যেহেতু প্রোগ্রামাররা কিছুতেই আসে না এমন কিছু নিয়ে "(" আমি কি সঠিকটি ব্যবহার করেছি? ") এমন কিছু না তা বোঝাতে সময় নিয়ে শেষ করি? ' টি ব্যাপার ("এখানে কি কোনও অন্তর্নির্মিত ধরণের উপস্থিত রয়েছে যা এই টেম্পলেট প্যারামিটারের জন্য প্রয়োজনীয় ইন্টারফেস প্রয়োগ করে?")। যদি টেমপ্লেট প্যারামিটারের কোনও সদস্য ব্যবহার করা হয় ( T t; int i = t.toInt();) তবে আপনার "রিয়েল ক্লাস" দরকার, এবং সরবরাহ করার intজন্য আপনার কোডটি সংকলন করবে না T...
স্টিভ জেসপ

1
আপনি যদি ব্যবহারটিকে আসল ক্লাসের মধ্যে সীমাবদ্ধ করতে চান তবে অ-শ্রেণীর ধরণের জন্য ত্রুটি ছুঁড়ে দেওয়ার / ঘটানোর জন্য বিশেষীকরণ যুক্ত করা ভাল। আপনি যদি নির্দিষ্ট ক্লাসে ব্যবহার সীমাবদ্ধ করতে চান তবে কেবল তাদের জন্য বিশেষীকরণ করুন। যাই হোক না কেন, এই ধরণের শৈলীগত পার্থক্যটি বার্তাটি পেতে খুব সূক্ষ্ম।
পোটোসওয়টার

2
যেহেতু তারা একই জিনিস বোঝায়, দয়া করে কেবল একটি ব্যবহার করুন। অন্যথায়, এটি মঙ্গলবার না হলে এটি ইনলাইন {ব্যবহার করার মতো, এবং তারপরে আপনি পরবর্তী লাইন {ব্যবহার করছেন {
পল ড্রপার

+1 আমি নিজেই এটি কখনও কখনও করি ... এর দ্বারা classবোঝা যায় যে আপনি সম্ভবত কোনও "মান" প্রত্যাশা করছেন না সম্ভবত কিছু অপারেটরকে সমর্থন করছেন, অনুলিপি করুন এবং নির্মাণ এবং / অথবা অ্যাসাইনমেন্টটি সরান, তবে নির্দিষ্টভাবে কিছু সদস্য অ্যাক্সেস শব্দার্থিককে সমর্থন করার জন্য একটি টাইপ প্রয়োজন। ঘোষণায় দ্রুততম নজরে প্রত্যাশাগুলি এবং নিরুৎসাহਤਾਂ সেট করে যেমন classপ্যারামিটারগুলির জন্য অন্তর্নির্মিত প্রকার সরবরাহ করা যখন তা অবশ্যই ত্রুটি হবে।
টনি ডেলরয়

আমি বুঝতে চাই যে কোন ধরণের বাস্তব-বিশ্বের পরিস্থিতি বিদ্যমান যেখানে কোনও টেমপ্লেট যে কোনও শ্রেণীর জন্য কাজ করবে, তবে অন্তর্নির্মিত ধরণের সাথে কাজ করবে না। আপনার কি উদাহরণ আছে?
lfalin

7
  1. কোনও পার্থক্য নেই
  2. টেমপ্লেট ধরণের পরামিতি Containerনিজেই দুটি ধরণের পরামিতিগুলির একটি টেম্পলেট।

3
সাধারণভাবে একটি পার্থক্য আছে।
হাসান সৈয়দ

এই দুটি পরামিতিটির ধারকটির নামও দেওয়া যেতে পারে? উদাহরণস্বরূপ তাদের কোনও নাম নেই। এবং এছাড়াও - এই উদাহরণে এটি 'ক্লাস কনটেইনার' লেখা আছে - এর পরিবর্তে সেখানে 'টাইপনেম কনটেইনার' লেখাও যেতে পারে?
মাদুর

2
@ ম্যাট: হ্যাঁ, অনুসন্ধানের শব্দটি হ'ল টেমপ্লেট টেম্পলেট পরামিতি / যুক্তি । উদাহরণস্বরূপ:template<template<class U> class V> struct C {};
জর্জিট ফ্রিটস্কে

6

এই টুকরো স্নিপেট সি ++ প্রাইমার বই থেকে প্রাপ্ত। যদিও আমি নিশ্চিত যে এটি ভুল।

প্রতিটি ধরণের প্যারামিটার অবশ্যই মূলশব্দ শ্রেণি বা টাইপনামের আগে হওয়া উচিত:

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

এই কীওয়ার্ডগুলির একই অর্থ রয়েছে এবং এটি একটি টেম্পলেট প্যারামিটার তালিকার অভ্যন্তরে বিনিময়যোগ্য হিসাবে ব্যবহার করা যেতে পারে। একটি টেম্পলেট প্যারামিটার তালিকা উভয় কীওয়ার্ড ব্যবহার করতে পারে:

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

টেমপ্লেট ধরণের পরামিতি নির্ধারণের জন্য শ্রেণীর পরিবর্তে কীওয়ার্ড টাইপনেমটি ব্যবহার করা আরও স্বজ্ঞাত বলে মনে হচ্ছে। সর্বোপরি, আমরা টেম্পলেট ধরণের আর্গুমেন্ট হিসাবে বিল্ট-ইন (ননক্লাস) প্রকারগুলি ব্যবহার করতে পারি। তদুপরি, টাইপনেম আরও স্পষ্টভাবে ইঙ্গিত দেয় যে এর পরে যে নামটি অনুসরণ করা হয় তা একটি টাইপের নাম। তবে, টেমপ্লেটগুলি ইতিমধ্যে ব্যাপকভাবে ব্যবহৃত হওয়ার পরে টাইপনেম সি ++ এ যুক্ত হয়েছিল; কিছু প্রোগ্রামার একচেটিয়াভাবে ক্লাস ব্যবহার চালিয়ে যায়

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