সি ++ টেম্পলেটগুলি যা কেবলমাত্র নির্দিষ্ট ধরণের গ্রহণ করে


158

জাভাতে আপনি জেনেরিক শ্রেণি সংজ্ঞায়িত করতে পারেন যা কেবলমাত্র আপনার ধরণের শ্রেণীর প্রসারিত প্রকারগুলিকে গ্রহণ করে:

public class ObservableList<T extends List> {
  ...
}

এটি "এক্সটেন্ডস" কীওয়ার্ড ব্যবহার করে করা হয়েছে।

এই কিওয়ার্ডের সি ++ তে কিছু সাধারণ সমতুল্য কি আছে?


ইতিমধ্যে বেশ পুরানো প্রশ্ন ... আমি অনুভব করছি যে এখানে কী অনুপস্থিত রয়েছে (উত্তরগুলি থেকেও) যে জাভা জেনেরিকস সত্যই সি ++ তে টেম্পলেটগুলির সমতুল্য নয়। সাদৃশ্য রয়েছে, তবে ইমো কারও কাছে সরাসরি জাভা সমাধানটি সি ++ তে সরাসরি অনুবাদ করার সাথে সাথে বুঝতে হবে যে তারা সম্ভবত বিভিন্ন ধরণের সমস্যার জন্য তৈরি হয়েছে;)
আইডাক্ল্যাভ 463035818

উত্তর:


104

আমি বুস্টের ধরণের বৈশিষ্ট্যযুক্ত গ্রন্থাগার থেকে কনসার্টে বুস্টের স্ট্যাটিক এ্যাসার বৈশিষ্ট্যটি ব্যবহার করার পরামর্শ দিচ্ছি is_base_of:

template<typename T>
class ObservableList {
    BOOST_STATIC_ASSERT((is_base_of<List, T>::value)); //Yes, the double parentheses are needed, otherwise the comma will be seen as macro argument separator
    ...
};

অন্য কয়েকটি, সহজ ক্ষেত্রে, আপনি কেবলমাত্র একটি বৈশ্বিক টেম্পলেটকে ফরওয়ার্ড-ডিক্লেয়ার করতে পারেন, তবে বৈধ প্রকারের জন্য এটি কেবল (স্পষ্টভাবে বা আংশিকভাবে বিশেষজ্ঞ) সংজ্ঞায়িত করতে পারেন:

template<typename T> class my_template;     // Declare, but don't define

// int is a valid type
template<> class my_template<int> {
    ...
};

// All pointer types are valid
template<typename T> class my_template<T*> {
    ...
};

// All other types are invalid, and will cause linker error messages.

[গৌণ সম্পাদনা 6/12/2013: একটি ঘোষিত-তবে-নয়-সংজ্ঞায়িত টেম্পলেট ব্যবহারের ফলে লিঙ্কার হবে , সংকলক নয়, ত্রুটি বার্তাগুলি]


স্ট্যাটিক asserts পাশাপাশি দুর্দান্ত। :)
ম্যাকবার্ডি

5
@ জন: আমি আশঙ্কা করছি যে বিশেষীকরণটি কেবল myBaseTypeঠিক মিলবে । বুস্টকে বরখাস্ত করার আগে, আপনার জানা উচিত যে এর বেশিরভাগটি কেবলমাত্র শিরোনামের টেমপ্লেট কোড - তাই আপনি যে জিনিসগুলি ব্যবহার করেন না তার জন্য রানটাইমের সময় কোনও মেমরি বা সময় ব্যয় নেই। এছাড়াও আপনি যে নির্দিষ্ট জিনিসগুলি এখানে ( BOOST_STATIC_ASSERT()এবং is_base_of<>) ব্যবহার করবেন তা কেবলমাত্র ঘোষণাপত্র (যেমন ফাংশন বা ভেরিয়েবলের কোনও প্রকৃত সংজ্ঞা নয় ) ব্যবহার করে প্রয়োগ করা যেতে পারে যাতে তারা কোনও স্থান বা সময় নেয় না।
j_random_hacker

50
সি ++ 11 এসেছে। এখন আমরা ব্যবহার করতে পারি static_assert(std::is_base_of<List, T>::value, "T must extend list")
সিয়ুয়ান রেন

2
বিটিডব্লিউ, ডাবল বন্ধনী আবশ্যক হওয়ার কারণটি হ'ল BOOST_STATIC_ASSERT একটি ম্যাক্রো এবং অতিরিক্ত বন্ধনী প্রিপ্রোসেসরকে দ্বিতীয় ম্যাক্রো যুক্তি হিসাবে is_base_of ফাংশন আর্গুমেন্টের মধ্যে কমা ব্যাখ্যা করতে বাধা দেয়।
jfritz42

1
@ আন্ড্রেয়ুয়া: আসলে কী অনুপস্থিত তা আমি বুঝতে পারি না। আপনি কোনও ভেরিয়েবল ঘোষণার চেষ্টা করতে পারেন my_template<int> x;বা my_template<float**> y;কম্পাইলার এগুলি অনুমতি দেয় my_template<char> z;তা যাচাই করতে পারেন এবং তারপরে কোনও ভেরিয়েবল ঘোষণা করে তা যাচাই করে না।
j_random_hacker

134

এটি অন্যান্য উত্তরগুলি যেমন উল্লেখ করেছে তেমন এটি সি ++ এ সাধারণত অনিয়ন্ত্রিত is সি ++ তে আমরা "এই শ্রেণীর উত্তরাধিকারী" ব্যতীত অন্যান্য প্রতিবন্ধকতার উপর ভিত্তি করে জেনেরিক ধরণের সংজ্ঞা দিতে থাকি tend আপনি যদি সত্যিই এটি করতে চেয়েছিলেন তবে সি ++ 11 এবং এটি করা বেশ সহজ <type_traits>:

#include <type_traits>

template<typename T>
class observable_list {
    static_assert(std::is_base_of<list, T>::value, "T must inherit from list");
    // code here..
};

এটি যদিও সি ++ তে প্রত্যাশা করে যেগুলি প্রচুর ধারণা ভাঙে। নিজের বৈশিষ্ট্যগুলি সংজ্ঞায়িত করার মতো কৌশলগুলি ব্যবহার করা ভাল। উদাহরণস্বরূপ, সম্ভবত observable_listযে কোনও ধরণের কন্টেইনারটি টাইপডেফ const_iteratorএবং একটি beginএবং endসদস্য ফাংশন রয়েছে তা গ্রহণ করতে চায় const_iterator। যদি আপনি এটিকে উত্তরাধিকার সূত্রে ক্লাসে সীমাবদ্ধ করেন listতবে কোনও ব্যবহারকারী যার নিজস্ব ধরণের রয়েছে যা উত্তরাধিকারসূত্রে আসে না listতবে এই সদস্য ফাংশনগুলি সরবরাহ করে এবং টাইপডেফগুলি আপনার ব্যবহার করতে অক্ষম হবে observable_list

এই ইস্যুটির দুটি সমাধান রয়েছে যার মধ্যে একটি হ'ল কোনও কিছুকে সীমাবদ্ধ করা এবং হাঁসের টাইপের উপর নির্ভর করা। এই সমাধানের জন্য একটি বৃহত কন এটি হ'ল এতে প্রচুর পরিমাণে ত্রুটি জড়িত যা ব্যবহারকারীর পক্ষে কুঁকানো শক্ত হতে পারে। আর একটি সমাধান হ'ল ইন্টারফেসের প্রয়োজনীয়তাগুলি পূরণ করতে সরবরাহ করা ধরণের সীমাবদ্ধতার জন্য বৈশিষ্ট্যগুলি সংজ্ঞায়িত করা। এই সমাধানের জন্য বড় কন এটি অতিরিক্ত লিখন জড়িত যা বিরক্তিকর হিসাবে দেখা যেতে পারে। তবে ইতিবাচক দিকটি হ'ল আপনি নিজের ত্রুটি বার্তাগুলি একটি লা লিখতে সক্ষম হবেন static_assert

সম্পূর্ণতার জন্য, উপরের উদাহরণটির সমাধান দেওয়া হল:

#include <type_traits>

template<typename...>
struct void_ {
    using type = void;
};

template<typename... Args>
using Void = typename void_<Args...>::type;

template<typename T, typename = void>
struct has_const_iterator : std::false_type {};

template<typename T>
struct has_const_iterator<T, Void<typename T::const_iterator>> : std::true_type {};

struct has_begin_end_impl {
    template<typename T, typename Begin = decltype(std::declval<const T&>().begin()),
                         typename End   = decltype(std::declval<const T&>().end())>
    static std::true_type test(int);
    template<typename...>
    static std::false_type test(...);
};

template<typename T>
struct has_begin_end : decltype(has_begin_end_impl::test<T>(0)) {};

template<typename T>
class observable_list {
    static_assert(has_const_iterator<T>::value, "Must have a const_iterator typedef");
    static_assert(has_begin_end<T>::value, "Must have begin and end member functions");
    // code here...
};

উপরে উদাহরণটিতে অনেকগুলি ধারণাগুলি দেখানো হয়েছে যা সি ++ 11 এর বৈশিষ্ট্যগুলি প্রদর্শন করে। কৌতূহলীদের জন্য কিছু অনুসন্ধান পদগুলি হ'ল ভ্যারিয়্যাডিক টেম্পলেটগুলি, SFINAE, এক্সপ্রেশন SFINAE এবং বৈশিষ্ট্যগুলি টাইপ করুন।


2
আমি বুঝতে পারিনি যে সি ++ টেম্পলেটগুলি আজ অবধি হাঁসের টাইপিং ব্যবহার করে। উদ্ভট ধরণের!
অ্যান্ডি

2
ব্যাপক নীতি বাধ্যবাধকতা দেওয়া সি ++ প্রচলন সি , নিশ্চিত করুন না কেন template<class T:list>এই ধরনের আপত্তিকর ধারণা। বখশিশের জন্য ধন্যবাদ.
বিভিজে

60

সহজ সমাধান, যা এখনও কেউ উল্লেখ করেনি, কেবলমাত্র সমস্যাটিকে উপেক্ষা করা। যদি আমি intকোনও ফাংশন টেম্পলেটে একটি টেম্পলেট প্রকার হিসাবে ব্যবহার করার চেষ্টা করি যা ভেক্টর বা তালিকার মতো ধারক শ্রেণীর প্রত্যাশা করে তবে আমি একটি সংকলন ত্রুটি পেয়ে যাব। অশোধিত এবং সহজ, তবে এটি সমস্যার সমাধান করে। সংকলকটি আপনি যে ধরণের নির্দিষ্ট করেছেন তা ব্যবহার করার চেষ্টা করবে এবং যদি এটি ব্যর্থ হয় তবে এটি একটি সংকলন ত্রুটি তৈরি করে।

এটির সাথে একমাত্র সমস্যাটি হ'ল যে ত্রুটি বার্তাগুলি আপনি পেয়েছেন তা পড়ার জন্য জটিল হয়ে উঠছে। তবু এটি এটি করার একটি খুব সাধারণ উপায়। স্ট্যান্ডার্ড লাইব্রেরিতে ফাংশন বা শ্রেণি টেম্পলেটগুলি পূর্ণ যা টেম্পলেট ধরণের থেকে নির্দিষ্ট আচরণের প্রত্যাশা করে এবং ব্যবহৃত প্রকারগুলি বৈধ কিনা তা যাচাই করার জন্য কিছুই করেন না।

আপনি যদি খুব ভাল ত্রুটি বার্তাগুলি চান (বা আপনি যদি এমন কেসগুলি ধরতে চান যা সংকলক ত্রুটি তৈরি করে না, তবে এখনও বোঝায় না) তবে আপনি এটি কতটা জটিল করতে চান তার উপর নির্ভর করে বুস্টের স্ট্যাটিক দাবী ব্যবহার করুন বা বুস্ট কনসেপ্ট_চেক লাইব্রেরি।

একটি আপ-টু-ডেট সংকলক সহ আপনার একটি বিল্ট-ইন রয়েছে static_assert, যা পরিবর্তে ব্যবহার করা যেতে পারে।


7
হ্যাঁ, আমি সবসময়ই ভেবেছিলাম যে টেম্পলেটগুলি সি ++ তে টাইপিংয়ের নিকটতম জিনিস। যদি এটিতে কোনও টেমপ্লেটের জন্য প্রয়োজনীয় সমস্ত উপাদান থাকে তবে এটি কোনও টেমপ্লেটে ব্যবহার করা যেতে পারে।

@ জন: আমি দুঃখিত, আমি এর মাথা বা লেজ বানাতে পারি না। কোন ধরণের T, এবং কোথা থেকে এই কোড বলা হয়? কিছু প্রসঙ্গ ছাড়াই, আমার কোড স্নিপেট বোঝার কোনও সুযোগ নেই। তবে আমি যা বলেছি তা সত্য। যদি আপনি toString()এমন কোনও ধরণের কল করতে চেষ্টা করেন যার কোনও toStringসদস্য ফাংশন নেই, তবে আপনি একটি সংকলন ত্রুটি পাবেন।
jalf

@ জন: পরের বার, সমস্যাটি আপনার কোড এ থাকলে সম্ভবত আপনার লোকজনকে কিছুটা কম ট্রিগার-হ্যাপী হওয়া উচিত
জাল্ফ

@ জালফ, ঠিক আছে +1 টি। এটি সেরা বানানোর চেষ্টা করে এটি একটি দুর্দান্ত উত্তর ছিল। ভুল লেখার জন্য দুঃখিত আমি ভেবেছিলাম আমরা টাইপটি ফাংশন টেম্পলেটগুলির জন্য নয় ক্লাসগুলির জন্য পরামিতি হিসাবে ব্যবহার করার বিষয়ে কথা বলছিলাম, যা আমি মনে করি প্রাক্তনের সদস্য তবে পতাকাটি সংকলকটির জন্য অনুরোধ করা দরকার।
জন

13

আমরা ব্যবহার করতে পারি std::is_base_ofএবং std::enable_if:
( static_assertউপরের ক্লাসগুলি মুছে ফেলা যায়, কাস্টম-প্রয়োগ করা যেতে পারে বা উত্সাহ থেকে ব্যবহার করা যেতে পারে যদি আমরা উল্লেখ না করতে পারি type_traits)

#include <type_traits>
#include <list>

class Base {};
class Derived: public Base {};

#if 0   // wrapper
template <class T> class MyClass /* where T:Base */ {
private:
    static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
    typename std::enable_if<std::is_base_of<Base, T>::value, T>::type inner;
};
#elif 0 // base class
template <class T> class MyClass: /* where T:Base */
    protected std::enable_if<std::is_base_of<Base, T>::value, T>::type {
private:
    static_assert(std::is_base_of<Base, T>::value, "T is not derived from Base");
};
#elif 1 // list-of
template <class T> class MyClass /* where T:list<Base> */ {
    static_assert(std::is_base_of<Base, typename T::value_type>::value , "T::value_type is not derived from Base");
    typedef typename std::enable_if<std::is_base_of<Base, typename T::value_type>::value, T>::type base; 
    typedef typename std::enable_if<std::is_base_of<Base, typename T::value_type>::value, T>::type::value_type value_type;

};
#endif

int main() {
#if 0   // wrapper or base-class
    MyClass<Derived> derived;
    MyClass<Base> base;
//  error:
    MyClass<int> wrong;
#elif 1 // list-of
    MyClass<std::list<Derived>> derived;
    MyClass<std::list<Base>> base;
//  error:
    MyClass<std::list<int>> wrong;
#endif
//  all of the static_asserts if not commented out
//  or "error: no type named ‘type’ in ‘struct std::enable_if<false, ...>’ pointing to:
//  1. inner
//  2. MyClass
//  3. base + value_type
}

13

যতদূর আমি জানি এটি বর্তমানে সি ++ তে সম্ভব নয়। তবে, নতুন সি ++ 0 এক্স স্ট্যান্ডার্ডে "ধারণাগুলি" নামে একটি বৈশিষ্ট্য যুক্ত করার পরিকল্পনা রয়েছে যা আপনি সন্ধান করছেন এমন কার্যকারিতা সরবরাহ করে। সি ++ ধারণা সম্পর্কে এই উইকিপিডিয়া নিবন্ধটি আরও বিশদে ব্যাখ্যা করবে।

আমি জানি এটি আপনার তাত্ক্ষণিক সমস্যার সমাধান করে না তবে কয়েকটি সি ++ সংকলক রয়েছে যা ইতিমধ্যে নতুন মান থেকে বৈশিষ্ট্যগুলি যুক্ত করা শুরু করেছে, সুতরাং ইতিমধ্যে ধারণাগুলির বৈশিষ্ট্যটি কার্যকর করেছে এমন একটি সংকলক খুঁজে পাওয়া সম্ভব হতে পারে।


4
দুর্ভাগ্যক্রমে ধারণাগুলি স্ট্যান্ডার্ড থেকে বাদ দেওয়া হয়েছে।
ম্যাকবার্ডি

4
C ++ 20 এর জন্য সীমাবদ্ধতা এবং ধারণা গ্রহণ করা উচিত।
পেট্রা জাভেরিক

static_assertঅন্যান্য উত্তরগুলি যেমন দেখায় তেমন ধারণা, ব্যবহার এবং SFINAE ছাড়াই এটিও সম্ভব । জাভা বা সি #, বা হাস্কেল (...) থেকে আসা কারওর জন্য বাকি সমস্যাটি হ'ল সি ++ 20 সংকলক জাভা এবং সি # যা প্রয়োজনীয় ধারণাগুলির বিরুদ্ধে সংজ্ঞা পরীক্ষা করে না।
ব্যবহারকারী 7610

10

আমার মনে হয় সমস্ত পূর্বের উত্তরগুলি গাছের জন্য বনের দৃষ্টি হারিয়েছে।

জাভা জেনেরিকগুলি টেম্পলেটগুলির মতো নয় ; তারা টাইপ ইরেজর ব্যবহার করে যা টাইম পলিমারফিজম সংকলন করার পরিবর্তে গতিশীল কৌশল , যা স্থির কৌশল । এই দুটি খুব ভিন্ন কৌশল কেন ভাল জেল না তা স্পষ্ট হওয়া উচিত।

একটি রান টাইমকে অনুকরণ করার জন্য একটি কমপাইল টাইম কনস্ট্রাক্ট ব্যবহার করার চেষ্টা করার পরিবর্তে আসুন extendsআসলে কী হয় তা দেখুন : স্ট্যাক ওভারফ্লো এবং উইকিপিডিয়া অনুসারে , সাবক্লাসিং নির্দেশ করতে এক্সটেন্ডস ব্যবহার করা হয়।

সি ++ সাবক্লাসিং সমর্থন করে।

আপনি একটি ধারক শ্রেণিও দেখান, যা জেনেরিক আকারে ধরণ মুছে ফেলা ব্যবহার করে এবং প্রকারের পরীক্ষা করতে প্রসারিত হয়। সি ++ এ আপনাকে নিজের মুছে ফেলা যন্ত্রপাতিটি নিজেই করতে হবে, যা সহজ: সুপারক্লাসে একটি পয়েন্টার তৈরি করুন।

পুরো ক্লাসটি তৈরির পরিবর্তে এটি ব্যবহার করা আরও সহজ করার জন্য এটি টাইপএডেপে জড়িয়ে রাখি, এবং ভয়েলা:

typedef std::list<superclass*> subclasses_of_superclass_only_list;

উদাহরণ স্বরূপ:

class Shape { };
class Triangle : public Shape { };

typedef std::list<Shape*> only_shapes_list;
only_shapes_list shapes;

shapes.push_back(new Triangle()); // Works, triangle is kind of shape
shapes.push_back(new int(30)); // Error, int's are not shapes

এখন, মনে হচ্ছে তালিকাটি একটি ইন্টারফেস যা এক ধরণের সংগ্রহের প্রতিনিধিত্ব করে। সি ++ এর একটি ইন্টারফেস কেবল একটি বিমূর্ত শ্রেণি হবে, এটি এমন একটি বর্গ যা খাঁটি ভার্চুয়াল পদ্ধতি ছাড়া কিছুই প্রয়োগ করে না। এই পদ্ধতিটি ব্যবহার করে, আপনি সহজেই কোনও ধারণা বা টেম্পলেট বিশেষায়নের ছাড়াই সি ++ তে আপনার জাভা উদাহরণটি প্রয়োগ করতে পারেন। এটি ভার্চুয়াল টেবিল চেহারা আপের কারণে জাভা শৈলীর জেনেরিকগুলির মতো ধীর সঞ্চালন করবে তবে এটি প্রায়শই গ্রহণযোগ্য ক্ষতি হতে পারে।


3
আমি এমন উত্তরের ফ্যান নই যা "এটি সুস্পষ্ট হওয়া উচিত" বা "প্রত্যেকেই জানে" এর মতো বাক্যাংশ ব্যবহার করে এবং তারপরে কোনটি সুস্পষ্ট বা সর্বজনবিদিত তা ব্যাখ্যা করার জন্য এগিয়ে যান। স্পষ্টতই প্রসঙ্গে, অভিজ্ঞতা এবং অভিজ্ঞতার প্রসঙ্গে। এ জাতীয় বক্তব্য সহজাত অভদ্র।
ডিভে

2
@ ডেভিডলাইভলি শিষ্টাচারের জন্য এই উত্তরটির সমালোচনা করতে প্রায় দু'বছর দেরী হয়েছে, তবে আমি এই নির্দিষ্ট ক্ষেত্রেও আপনার সাথে একমত নই; আমি ব্যাখ্যা করেছিলাম যে কেন তারা দুটি কৌশল একসাথে যায় না তা উল্লেখ করার আগে , পরে নয় obvious আমি প্রসঙ্গটি সরবরাহ করেছি এবং তারপরে বলেছি যে প্রসঙ্গটি থেকে উপসংহারটি সুস্পষ্ট ছিল। এটি আপনার ছাঁচে ঠিক ফিট করে না।
এলিস

এই উত্তরের লেখক কিছু ভারী উত্তোলন করার পরে কিছু স্পষ্ট বলেছিলেন। আমি মনে করি না যে সমাধানটি স্পষ্ট ছিল বলে লেখকের উদ্দেশ্য ছিল।
লুক গহর্সাম

10

একটি সমতুল্য যা কেবল টাইপ তালিকা থেকে প্রাপ্ত টাইপগুলি টির মতো লাগে

template<typename T, 
         typename std::enable_if<std::is_base_of<List, T>::value>::type* = nullptr>
class ObservableList
{
    // ...
};

8

কার্যনির্বাহী সারাংশ: এটি করবেন না।

j_random_hacker এর উত্তর আপনাকে কীভাবে এটি করতে হবে তা বলে । তবে, আমি এটি উল্লেখ করতে চাই যে আপনার এটি করা উচিত নয় । টেম্পলেটগুলির সম্পূর্ণ বিন্দুটি হ'ল তারা যে কোনও সামঞ্জস্যপূর্ণ প্রকার গ্রহণ করতে পারে এবং জাভা শৈলীর ধরণের সীমাবদ্ধতাগুলি এটি ভেঙে দেয়।

জাভার ধরণের সীমাবদ্ধতাগুলি কোনও বাগ নয় যা কোনও বৈশিষ্ট্য নয়। তারা সেখানে আছে কারণ জাভা জেনেরিকের উপর মুছে ফেলা টাইপ করে, তাই জাভা একাই টাইপ প্যারামিটারের মানের ভিত্তিতে কীভাবে পদ্ধতিগুলি কল করতে পারেন তা নির্ধারণ করতে পারে না।

অন্যদিকে সি ++ এর তেমন কোনও বাধা নেই। টেমপ্লেট প্যারামিটার প্রকারগুলি যে ধরণের সাথে তারা ব্যবহার করা হয় তার সাথে সামঞ্জস্য হতে পারে। একটি সাধারণ বেস শ্রেণি হতে হবে না। এটি পাইথনের "হাঁসের টাইপিংয়ের মতো" তবে সংকলন সময়ে করা হয়েছে।

টেমপ্লেটগুলির শক্তি দেখানোর একটি সাধারণ উদাহরণ:

// Sum a vector of some type.
// Example:
// int total = sum({1,2,3,4,5});
template <typename T>
T sum(const vector<T>& vec) {
    T total = T();
    for (const T& x : vec) {
        total += x;
    }
    return total;
}

এই যোগফলটি সঠিক ক্রিয়াকলাপগুলিকে সমর্থন করে এমন কোনও ধরণের ভেক্টরকে যোগ করতে পারে। এটি আন্তঃ / দীর্ঘ / ভাসা / ডাবল এবং ব্যবহারকারী সংজ্ঞায়িত সংখ্যার প্রকারের সাথে + + অপারেটরকে ওভারলোড উভয়ের সাথেই কাজ করে। হেক, আপনি এমনকি স্ট্রিংগুলিতে যোগ দিতে এই ফাংশনটি ব্যবহার করতে পারেন, যেহেতু তারা ++ সমর্থন করে।

আদিমদের বক্সিং / আনবক্সিংয়ের প্রয়োজন নেই।

দ্রষ্টব্য যে এটি টি () ব্যবহার করে টি এর নতুন দৃষ্টান্তও তৈরি করে। অন্তর্নির্মিত ইন্টারফেস ব্যবহার করে এটি সি ++ তে তুচ্ছ, তবে জাভাতে টাইপ সীমাবদ্ধতার সাথে সত্যই সম্ভব নয়।

যদিও সি ++ টেমপ্লেটগুলিতে স্পষ্টত ধরণের বাধা নেই, তারা এখনও নিরাপদে টাইপ করে এবং সঠিক ক্রিয়াকলাপ সমর্থন করে না এমন কোড দিয়ে সংকলন করবে না।


2
আপনি যদি কখনও টেমপ্লেটগুলিকে বিশেষীকরণ না করার পরামর্শ দিচ্ছেন তবে আপনি ভাষাতে এটি কেন ব্যাখ্যা করতে পারেন?

1
আমি আপনার বক্তব্যটি পেয়েছি, তবে যদি আপনার টেম্পলেট যুক্তিটি নির্দিষ্ট ধরণের থেকে উদ্ভূত হওয়া উচিত তবে সাধারণ সংকলক ত্রুটি বমি করার চেয়ে স্ট্যাটিক_সেটর থেকে বার্তাটি ব্যাখ্যা করা সহজ হওয়া ভাল।
jhoffman0x

1
হ্যাঁ, সি ++ এখানে আরও অভিব্যক্তিপূর্ণ, তবে এটি সাধারণত একটি ভাল জিনিস (কারণ আমরা কম দিয়ে আরও প্রকাশ করতে পারি), কখনও কখনও আমরা ইচ্ছাকৃতভাবে আমাদের যে শক্তি দিয়ে থাকি তা সীমাবদ্ধ করতে চাই , নিশ্চিত করতে যে আমরা কোনও সিস্টেমকে পুরোপুরি বুঝতে পারি।
j_random_hacker

@ কার্গ টাইপ স্পেশালাইজিং তখন দরকারী যখন আপনি এমন কিছু কাজের সুযোগ নিতে সক্ষম হবেন যা কেবলমাত্র নির্দিষ্ট ধরণের জন্যই করা যায়। উদাহরণস্বরূপ, একটি বুলিয়ান ~ সাধারণত each প্রতিটি বাইট হয়, যদিও একটি বাইট ~ সাধারণত ~ 8 বিট / বুলিয়ান ধরে রাখতে পারে; একটি টেম্পলেট সংগ্রহের ক্লাস বুলিয়ানটির জন্য (এবং স্ট্যান্ডার্ড :: ম্যাপের ক্ষেত্রে) বিশেষীকরণ করতে পারে যাতে এটি স্মৃতি সংরক্ষণের জন্য ডেটা আরও শক্ত করে প্যাক করতে পারে।
থোকোশম্যান

এছাড়াও, স্পষ্ট করার জন্য, এই উত্তরটি "টেম্পলেটগুলিকে কখনও বিশেষীকরণ করবেন না" বলা হয় না এটি কোন বৈশিষ্ট্যটি কোনও টেম্পলেট দিয়ে কী কী ব্যবহার করা যায় তা সীমাবদ্ধ করার চেষ্টা করার জন্য সেই বৈশিষ্ট্যটি ব্যবহার করবেন না।
thecoshman

6

প্লেইন সি ++ এ এটি সম্ভব নয়, তবে আপনি কনসেপ্ট চেকিংয়ের মাধ্যমে সংকলন সময়ে টেমপ্লেট প্যারামিটারগুলি যাচাই করতে পারেন, যেমন বুস্টের বিসিসিএল ব্যবহার করে ।

সি ++ ২০ অনুসারে, ধারণাগুলি ভাষার একটি অফিশিয়াল বৈশিষ্ট্য হয়ে উঠছে ।


2
ওয়েল, এটা হয় সম্ভব, কিন্তু ধারণা পরীক্ষণ এখনও একটি ভাল ধারণা। :)
j_random_hacker

আমি আসলে বুঝিয়েছি যে এটি "সরল" সি ++ তে সম্ভব ছিল না। ;)
ম্যাকবার্ডি

5
class Base
{
    struct FooSecurity{};
};

template<class Type>
class Foo
{
    typename Type::FooSecurity If_You_Are_Reading_This_You_Tried_To_Create_An_Instance_Of_Foo_For_An_Invalid_Type;
};

নিশ্চিত হয়ে নিন যে উদ্ভূত শ্রেণিগুলি ফুসিকিউরিটি কাঠামোর উত্তরাধিকারী এবং সংকলক সমস্ত সঠিক জায়গায় বিচলিত হবে।


@ জেহেলভিয়ন Type::FooSecurityটেম্পলেট শ্রেণিতে ব্যবহৃত হয়। ক্লাসটি যদি টেমপ্লেট আর্গুমেন্টে পাস হয় তবে না FooSecurity, এটি ব্যবহারের চেষ্টা করার ফলে একটি ত্রুটি ঘটায়। এটি নিশ্চিত যে টেমপ্লেট আর্গুমেন্টে শ্রেণি পাস করা FooSecurity না থাকলে এটি থেকে উদ্ভূত হয় না Base
জিঞ্জারপ্লাস প্লাস প্লাস্টিক

2

সি ++ ২০ ধারণা ব্যবহার

https://en.cppreferences.com/w/cpp/language/constraints cppreferences সুস্পষ্ট ধারণা উদাহরণ হিসাবে উত্তরাধিকার ব্যবহারের কেস দিচ্ছে:

template <class T, class U>
concept Derived = std::is_base_of<U, T>::value;
 
template<Derived<Base> T>
void f(T);  // T is constrained by Derived<T, Base>

একাধিক ঘাঁটির জন্য আমি অনুমান করছি বাক্য গঠনটি হ'ল:

template <class T, class U, class V>
concept Derived = std::is_base_of<U, T>::value || std::is_base_of<V, T>::value;
 
template<Derived<Base1, Base2> T>
void f(T);

জিসিসি 10 এটি প্রয়োগ করেছে বলে মনে হয়: https://gcc.gnu.org/gcc-10/changes.html এবং আপনি এটি উবুন্টু 20.04 এ পিপিএ হিসাবে পেতে পারেন । https://godbolt.org/ আমার স্থানীয় জিসিসি 10.1 conceptএখনও সনাক্ত করতে পারেনি, তাই কী হচ্ছে তা নিশ্চিত হন না।


1

এই কিওয়ার্ডের সি ++ তে কিছু সাধারণ সমতুল্য কি আছে?

না।

আপনি কী অর্জন করতে চাইছেন তার উপর নির্ভর করে পর্যাপ্ত (বা আরও ভাল) বিকল্প থাকতে পারে।

আমি কয়েকটি এসটিএল কোড দেখেছি (লিনাক্সে, আমি মনে করি এটি এসজিআই এর বাস্তবায়ন থেকে প্রাপ্ত)। এটির "ধারণার প্রতিপত্তি" রয়েছে; উদাহরণস্বরূপ, আপনার যদি এমন কোনও ধরণের প্রয়োজন হয় যা বোঝে *xএবং ++x, ধারণারত দাবিতে কোনও কোড-না-ফাংশনে (বা অনুরূপ কিছু) কোড থাকে। এটির জন্য কিছু ওভারহেডের প্রয়োজন হয়, সুতরাং এটি কোনও ম্যাক্রোতে রাখার জন্য স্মার্ট হতে পারে যার সংজ্ঞা নির্ভর করে #ifdef debug

সাবক্লাস সম্পর্কটি যদি সত্যই আপনি জানতে চান তবে আপনি কনস্ট্রাক্টারে দৃsert়তার সাথে বলতে পারেন যে T instanceof list(এটি C ++ তে আলাদাভাবে "বানান" বাদে)। এইভাবে, আপনি আপনার জন্য এটি পরীক্ষা করতে সক্ষম না হয়ে সংকলক থেকে বেরিয়ে আসার পথ পরীক্ষা করতে পারেন।


1

এই ধরণের চেকগুলির জন্য কোনও কীওয়ার্ড নেই, তবে আপনি এতে কিছু কোড রাখতে পারেন যাতে কমপক্ষে একটি সুশৃঙ্খলভাবে ব্যর্থ হবে:

(1) আপনি যদি কোনও নির্দিষ্ট বেস শ্রেণীর প্যারামিটারগুলি গ্রহণ করতে কোনও ফাংশন টেম্পলেট চান তবে এটি আপনার ফাংশনে এক্স রেফারেন্সে অর্পণ করুন। (২) আপনি যদি ফাংশনগুলি গ্রহণ করতে চান তবে আদিম বা বিপরীতে নয়, বা আপনি অন্য উপায়ে ক্লাসগুলি ফিল্টার করতে চান তবে আপনার ফাংশনটির মধ্যে একটি (খালি) টেম্পলেট সহায়ক ফাংশন কল করুন যা কেবলমাত্র আপনি গ্রহণ করতে চান এমন ক্লাসগুলির জন্য সংজ্ঞায়িত।

পুরো ক্লাসে এই ধরণের চেকগুলিকে বাধ্য করার জন্য আপনি কোনও শ্রেণীর সদস্য ফাংশনে (1) এবং (2) ব্যবহার করতে পারেন।

আপনার ব্যথা কমাতে আপনি সম্ভবত এটি কিছু স্মার্ট ম্যাক্রোতে রেখে দিতে পারেন। :)


-2

ভাল, আপনি এই জাতীয় কিছু পড়ার জন্য আপনার টেম্পলেট তৈরি করতে পারেন:

template<typename T>
class ObservableList {
  std::list<T> contained_data;
};

এটি বিধিনিষেধকে অন্তর্নিহিত করে তুলবে, এছাড়াও আপনি কেবল তালিকার মতো দেখতে কিছু সরবরাহ করতে পারবেন না। ব্যবহৃত ধারক প্রকারগুলিকে সীমাবদ্ধ করার অন্যান্য উপায় রয়েছে, উদাহরণস্বরূপ নির্দিষ্ট আইটিরেটর প্রকারগুলি ব্যবহার করে যা সমস্ত পাত্রে বিদ্যমান নয় তবে আবার এটি স্পষ্ট বাধা ছাড়াই আরও স্পষ্ট।

আমার জ্ঞানের সর্বোপরি এমন একটি নির্মাণ যা জাভা বিবৃতিটিকে তার সম্পূর্ণ পরিসরে আয়না দেয় বর্তমান মানদণ্ডে বিদ্যমান নেই।

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

সি ++ ১১-এ, ধারণাগুলির প্রবর্তনকে এটিকে আরও সহজ করে তুলতে হবে তবে আমি মনে করি না যে এটি আপনি যা চান ঠিক তা করবে।

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