কেন কনস্ট্রাক্টর থেকে টেমপ্লেট পরামিতি নির্ধারণ করা হচ্ছে না?


102

আমার আজকের প্রশ্নটি বেশ সহজ: ক্লাস কনস্ট্রাক্টরের কাছ থেকে সংকলক টেমপ্লেট পরামিতিগুলি কেন ফাংশন পরামিতি থেকে করতে পারে না? উদাহরণস্বরূপ, নিম্নলিখিত কোডটি বৈধ হতে পারে না কেন:

template<typename obj>
class Variable {
      obj data;
      public: Variable(obj d)
              {
                   data = d;
              }
};

int main()
{
    int num = 2;
    Variable var(num); //would be equivalent to Variable<int> var(num),
    return 0;          //but actually a compile error
}

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


আমি কাউকে আমন্ত্রণ জানাব (আমি এখনই এটি করি না), দ্রহাকর এবং পাইটিস উত্তরটি কমপক্ষে কমপ্লেক্স করার জন্য (কমপক্ষে) কেন এটি কাজ করতে পারে না
jpinto3912

2
এছাড়াও লক্ষ করুন যে এটি সহজেই এর মাধ্যমে কাজ করা হয়template<class T> Variable<T> make_Variable(T&& p) {return Variable<T>(std::forward<T>(p));}
মুইং হাঁস

3
আপনি যা চান তার ক্রমটি পরিবর্তন করতে পারেন var = পরিবর্তনশীল <ডিক্লাইপ (এন)> (এন);
কোয়ান্টিনুক

18
সি ++ 17 এটি অনুমতি দেবে! এই প্রস্তাব গৃহীত হয়েছে: ওপেন-std.org/jtc1/sc22/wg21/docs/papers/2015/p0091r0.html
আন্ডারস্কোর_ডি

1
পছন্দ করুন প্রায় সময়! এটি আমার পক্ষে স্বাভাবিক অনুভূত হয়েছিল যেভাবে এটি কাজ করা উচিত এবং বিরক্তির উত্স যা এটি হয়নি।
amdn

উত্তর:


46

আমি মনে করি এটি বৈধ নয় কারণ কনস্ট্রাক্টর সর্বদা ক্লাসে প্রবেশের একমাত্র পয়েন্ট নয় (আমি কপি কন্সট্রাক্টর এবং অপারেটর সম্পর্কে বলছি =)। সুতরাং ধরুন আপনি নিজের ক্লাসটি এভাবে ব্যবহার করছেন:

MyClass m(string s);
MyClass *pm;
*pm = m;

আমি নিশ্চিত নই যে পার্সারের পক্ষে মাইক্লাস পিএমটি কী টেম্পলেট প্রকার তা জানা খুব স্পষ্ট হবে কিনা;

আমি যা বলেছি তা বোধগম্য হলেও কিছু মন্তব্য যুক্ত করতে নির্দ্বিধায় কিনা তা নিশ্চিত নই, এটি একটি আকর্ষণীয় প্রশ্ন।

সি ++ 17

এটি গৃহীত যে সি ++ 17 এর কনস্ট্রাক্টর আর্গুমেন্ট থেকে টাইপ ছাড় থাকবে।

উদাহরণ:

std::pair p(2, 4.5);
std::tuple t(4, 3, 2.5);

গৃহীত কাগজ


8
এটি আসলে একটি দুর্দান্ত পয়েন্ট যা আমি কখনই বিবেচনা করি নি। আমি পয়েন্টারটি টাইপ নির্দিষ্ট (যেমন এটি মাইক্লাস <স্ট্রিং> * বিকাল হতে হবে) হতে হবে এই সত্যের আশেপাশে কোনও উপায় দেখছি না। যদি এটি হয় তবে আপনারা যা করতে চান তা হ'ল তাত্ক্ষণিকতার ধরণ নির্দিষ্ট করা থেকে নিজেকে বাঁচানো; অতিরিক্ত কাজের কয়েকটি নিখুঁত অক্ষর (এবং কেবলমাত্র উপরের মত বস্তুটি স্ট্যাকের উপরে তৈরি করা হয়েছে, গাদা নয়)। আমি সর্বদা সন্দেহ করেছিলাম যে শ্রেণি অনুকরণ কৃমির সিনট্যাকটিক ক্যান খুলতে পারে এবং আমি মনে করি এটি এটি হতে পারে।
জিআরবি

2
আমি ঠিক দেখতে পাচ্ছি না যে কীভাবে কনস্ট্রাক্টরদের থেকে টেমপ্লেট-প্যারামিটার অনুমিতকরণের অনুমতি দেওয়ার জন্য আপনার দ্বিতীয় লাইনের মতো কনস্ট্রাক্টর কল ছাড়াই অ-বিশেষায়িত ঘোষণার অনুমতি দেওয়া দরকার । অর্থাৎ, MyClass *pmএখানে একই কারণে অবৈধ হবে যে ঘোষিত কোনও ফাংশন template <typename T> void foo();সুস্পষ্ট বিশিষ্টতা ছাড়াই ডাকা যাবে না।
কাইল স্ট্র্যান্ড

3
@ কাইলস্ট্র্যান্ড হ্যাঁ, 'ক্লাস টেম্পলেট যুক্তিগুলি তাদের নির্মাতাদের থেকে অনুমান করা যায় না কারণ [উদাহরণস্বরূপ যে কোনও নির্মাণকারী ব্যবহার করে না] ', এই উত্তরটি সম্পূর্ণ অপ্রাসঙ্গিক। আমি সত্যই বিশ্বাস করতে পারি না যে এটি গৃহীত হয়েছিল, +২২ এ পৌঁছেছে, কারও কাছে চমকপ্রদ সমস্যাটি লক্ষ্য করতে years বছর সময় নিয়েছিল এবং 7 বছর কোনও একক ডাউনওয়েট ছাড়াই বসেছিল। পড়ার সময় অন্য কেউ ভাবেন না, বা ...?
আন্ডারস্কোর_১১

1
@ আসর_আর_আমি কীভাবে পছন্দ করি, যেমনটি বর্তমানে দাঁড়িয়ে আছে, এই উত্তরটি বলছে "এই প্রস্তাবটিতে কিছু সমস্যা হতে পারে; আমি ঠিক জানি না যে আমি যা বলেছি তা বুদ্ধিমান হয়েছে (!), মন্তব্য করতে নির্দ্বিধায় (!!); এবং ওহ উপায় হ'ল সি ++ 17 কীভাবে কাজ করবে এটি ঠিক ঠিক ""
কাইল স্ট্র্যান্ড

1
@ কাইলস্ট্র্যান্ড আহা হ্যাঁ, এটি এখনও অন্য একটি বিষয়, যা আমি লক্ষ্য করেছি তবে অন্য সমস্ত মজার মধ্যে উল্লেখ করতে ভুলে গিয়েছি। সি ++ 17 সম্পর্কে সম্পাদনাটি ওপি দ্বারা নয় ... এবং আইএমও অনুমোদিত হওয়া উচিত ছিল না, তবে একটি নতুন উত্তর হিসাবে পোস্ট করা হয়েছে: পোস্টটি থাকলেও এটি 'পোস্টের অর্থের পরিবর্তন' হিসাবে অস্বীকারযোগ্য হত শুরু করার অর্থহীন ছিল ... আমি সম্পাদনা সম্পর্কে সচেতন ছিলাম না পুরোপুরি নতুন বিভাগগুলি ন্যায্য খেলা ছিল এবং অবশ্যই কম কঠোর সম্পাদনাগুলি প্রত্যাখ্যান করা হয়েছিল, তবে আমি অনুমান করি যে পর্যালোচকরা আপনি যে পদে পদক্ষেপ নেবেন সেই দিকটিই ড্রয়ের ভাগ্য।
আন্ডারস্কোর_১১

27

অন্যান্য লোকেরা যে কারণে সম্বোধন করেছে তার জন্য আপনি যা চান তা আপনি করতে পারবেন না তবে আপনি এটি করতে পারেন:

template<typename T>
class Variable {
    public: Variable(T d) {}
};
template<typename T>
Variable<T> make_variable(T instance) {
  return Variable<T>(instance);
}

যা সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে একই জিনিস আপনি চাইছেন। আপনি যদি এনক্যাপসুলেশন পছন্দ করেন তবে আপনি Make_variable কে একটি স্ট্যাটিক সদস্য ফাংশন বানাতে পারেন। এটাকেই মানুষ নামক কনস্ট্রাক্টর বলে। সুতরাং এটি কেবল যা করতে চায় তা করে না তবে এটি আপনাকে যা চায় তা প্রায় বলা হয়: সংকলকটি (নামযুক্ত) কনস্ট্রাক্টরের কাছ থেকে টেমপ্লেট প্যারামিটারটি infering করছে।

নোট: যে কোনও যুক্তিসঙ্গত সংকলক যখন আপনি এর মতো কিছু লেখেন তখন অস্থায়ী অবজেক্টটি অপ্টিমাইজ করবে

auto v = make_variable(instance);

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

3
এবং আরও ভাল সি ++ এ আপনি করতে পারেন auto v = make_variable(instance)তাই আপনাকে আসলে
ধরণটি

1
হ্যাঁ, মেকআপ ফাংশনটিকে staticসদস্য হিসাবে ঘোষণার ধারণাটিতে হাহাকার করুন ... এক সেকেন্ড জুয়েস্টের জন্য এটি সম্পর্কে ভাবেন। সরাইয়া যে: মুক্ত ফাংশন প্রকৃতপক্ষে ছিল সমাধান, কিন্তু এটা অপ্রয়োজনীয় boilerplate, অনেক, যখন তুমি টাইপিং এটা, আপনি শুধু যে জানেন কারণে আপনি কম্পাইলার সব অ্যাক্সেস তথ্য আপনি পুনরাবৃত্তি করছি রয়েছে থাকবে না। .. এবং ধন্যবাদ C ++ 17 canonises যে।
আন্ডারস্কোর_১১

21

২০১ belt সালের আলোকিত যুগে, আমাদের বেল্টের অধীনে দুটি নতুন মানদণ্ডের সাথে এই প্রশ্নটি জিজ্ঞাসা করা হয়েছিল এবং ঠিক কোণার চারপাশে একটি নতুন প্রশ্ন রয়েছে, জেনে রাখা গুরুত্বপূর্ণ বিষয়টি হ'ল সি ++ 17 স্ট্যান্ডার্ডকে সমর্থনকারী সংকলকরা আপনার কোডটি যেমনটি ঠিক তেমন সংকলন করবে

C ++ 17 এ শ্রেণি টেম্পলেটগুলির জন্য টেম্পলেট-যুক্তি ছাড়

এখানে (স্বীকৃত উত্তরের ওলঝাস ঝুমাব্যাকের সম্পাদনার সৌজন্যে) স্ট্যান্ডার্ডে প্রাসঙ্গিক পরিবর্তনগুলি বিশদযুক্ত কাগজটি।

অন্যান্য উত্তর থেকে উদ্বেগের সমাধান

বর্তমান শীর্ষ রেট উত্তর

এই উত্তরটি নির্দেশ করে যে "অনুলিপি নির্মাণকারী এবং operator=" সঠিক টেম্পলেট বিশেষণাদি জানত না।

এটি আজেবাজে কথা, কারণ মানক অনুলিপি-নির্মাতা এবং operator= কেবল একটি পরিচিত টেম্পলেট ধরণের জন্য বিদ্যমান :

template <typename T>
class MyClass {
    MyClass(const MyClass&) =default;
    ... etc...
};

// usage example modified from the answer
MyClass m(string("blah blah blah"));
MyClass *pm;   // WHAT IS THIS?
*pm = m;

এখানে, আমি মন্তব্য উল্লেখ করেছি, এমন হয় কোন কারণ জন্য MyClass *pmসহ বা অনুমান নতুন ফর্ম ছাড়া একটি আইনি ঘোষণা করা: MyClass একটি টাইপ নয় (এটি একটি টেমপ্লেট), তাই এটি অর্থে দেখা যায় না একটি পয়েন্টার ডিক্লেয়ার করার মত প্রকার MyClass। উদাহরণটি ঠিক করার একটি সম্ভাব্য উপায় এখানে:

MyClass m(string("blah blah blah"));
decltype(m) *pm;               // uses type inference!
*pm = m;

এখানে, pmহয় ইতিমধ্যে সঠিক ধরনের, এবং তাই অনুমান তুচ্ছ হয়। তদুপরি, অনুলিপি করে অনুলিপিটি মিশ্রিত করা অসম্ভবভাবে অনুলিপি করে যখন কপি-নির্মাণকারীকে কল করে:

MyClass m(string("blah blah blah"));
auto pm = &(MyClass(m));

এখানে, pmএকটি অনুলিপি পয়েন্টার হবে m। এখানে, MyClassথেকে কপি-নির্মাণ করা হচ্ছে m-যেটা ধরনের হয় MyClass<string>(এবং না অবাস্তব ধরনের MyClass)। সুতরাং, যেখানে এ pm'র টাইপ অনুমিত হয়, হয় জানাতে চাই যে, এর টেমপ্লেট-টাইপ যথেষ্ট তথ্য m, সেইজন্য এবং এর টেমপ্লেট-টাইপ pmহয় string

তদতিরিক্ত, নিম্নলিখিতগুলি সর্বদা একটি সংকলন ত্রুটি উত্থাপন করবে :

MyClass s(string("blah blah blah"));
MyClass i(3);
i = s;

এটি কারণ অনুলিপি নির্মাণকারীর ঘোষণাগুলি তাত্পর্যপূর্ণ নয় :

MyClass(const MyClass&);

এখানে, অনুলিপি-নির্মাণকারী যুক্তির টেম্পলেট-টাইপ সামগ্রিকভাবে শ্রেণীর টেম্পলেট-টাইপের সাথে মেলে ; অর্থাত, যখন MyClass<string>instantiated হয়, MyClass<string>::MyClass(const MyClass<string>&);এটা দিয়ে instantiated করা হয়, এবং যখন MyClass<int>instantiated হয়, MyClass<int>::MyClass(const MyClass<int>&);instantiated করা হয়। যতক্ষণ না এটি স্পষ্টভাবে নির্দিষ্ট না করা হয় বা একটি তদন্তকারী নির্মাণকারীর ঘোষণা না দেওয়া হয় MyClass<int>::MyClass(const MyClass<string>&);, সংকলকটির তাত্ক্ষণিক কারণ হওয়ার কোনও কারণ নেই , যা স্পষ্টতই অনুপযুক্ত।

ক্যাটালিন পিটিয়সের উত্তর ș

পিতি কেটে নেওয়ার উদাহরণ দেয় Variable<int>এবং Variable<double>বলে:

দুটি ভিন্ন ধরণের (ভেরিয়েবল এবং ভেরিয়েবল) কোডে আমার একই ধরণের নাম (ভেরিয়েবল) রয়েছে। আমার বিষয়ভিত্তিক দৃষ্টিকোণ থেকে, এটি কোডের পঠনযোগ্যতাকে অনেক বেশি প্রভাবিত করে।

আগের উদাহরণে উল্লিখিত Variableনিজেই না একটি টাইপ নাম, যদিও নতুন বৈশিষ্ট্য তোলে এক চিহ্নগুলি সিন্টেক্সের মত চেহারা।

পিতি তারপরে জিজ্ঞাসা করে যে কোনও কনস্ট্রাক্টর না দেওয়া হয়েছে যা উপযুক্ত অনুমানের অনুমতি দেয়। উত্তরটি হ'ল কোনও অনুমানের অনুমতি নেই, কারণ কনস্ট্রাক্টর কল দ্বারা অনুমানটি ট্রিগার করা হয়েছে । কনস্ট্রাক্টর-কল ছাড়া কোনও অনুকরণ নেই

এটি fooএখানে কোন সংস্করণটি বাদ দেওয়া হবে তা জিজ্ঞাসার অনুরূপ :

template <typename T> foo();
foo();

উত্তরটি হ'ল এই কোডটি অবৈধ, কারণটির কারণেই।

এমসাল্টারের উত্তর

এটি, যতদূর আমি বলতে পারি, প্রস্তাবিত বৈশিষ্ট্যটি সম্পর্কে বৈধ উদ্বেগ প্রকাশের একমাত্র উত্তর।

উদাহরণটি হ'ল:

Variable var(num);  // If equivalent to Variable<int> var(num),
Variable var2(var); // Variable<int> or Variable<Variable<int>> ?

মূল প্রশ্নটি হ'ল সংকলকটি কি এখানে টাইপ-ইনফেরার্ড কন্সট্রাক্টর বা কপি কনস্ট্রাক্টর নির্বাচন করে?

কোডটি চেষ্টা করে দেখতে পেলাম আমরা অনুলিপি নির্মাণকারী নির্বাচিত হয়েছি। উদাহরণটি প্রসারিত করতে :

Variable var(num);          // infering ctor
Variable var2(var);         // copy ctor
Variable var3(move(var));   // move ctor
// Variable var4(Variable(num));     // compiler error

প্রস্তাব এবং আদর্শের নতুন সংস্করণটি কীভাবে এটি নির্দিষ্ট করে আমি নিশ্চিত নই; এটি "ছাড়ের গাইড" দ্বারা নির্ধারিত বলে মনে হয় যা স্ট্যান্ডার্ডিজের একটি নতুন বিট যা আমি এখনও বুঝতে পারি না।

var4ছাড়ও কেন অবৈধ তা আমিও নিশ্চিত নই ; জি ++ থেকে সংকলক ত্রুটিটি ইঙ্গিত করে যে বিবৃতিটি একটি কার্য ঘোষণার হিসাবে পার্স করা হচ্ছে।


কি দুর্দান্ত, বিস্তারিত উত্তর! var4এটি "সর্বাধিক ভেক্সিং পার্স" (টেমপ্লেট আরগ ছাড়ের সাথে সম্পর্কিত নয়) কেবল একটি ঘটনা। আমরা এটির জন্য কেবল অতিরিক্ত পেরেন ব্যবহার করতাম, তবে এই দিনগুলিকে আমি মনে করি নির্মাণগুলি নিস্পষ্টতার সাথে বোঝাতে ব্যবহার করা স্বাভাবিক পরামর্শ।
সুমুডু ফার্নান্দো

@ সুমুডু ফার্নান্দো ধন্যবাদ! আপনি কি বোঝাতে চান যে Variable var4(Variable(num));এটি একটি ফাংশন ঘোষণা হিসাবে বিবেচিত হয়? যদি তা হয় তবে কেন Variable(num)একটি বৈধ প্যারামিটারের বিশদকরণ?
কাইল স্ট্র্যান্ড

@ সুমুডু ফার্নান্দো কিছু মনে করবেন না, আমার ধারণা ছিল না এটি কার্যকর ছিল: coliru.stacked-crooked.com/a/98c36b8082660941
কাইল স্ট্র্যান্ড

11

এখনও নিখোঁজ: এটি নীচের কোডটিকে বেশ অস্পষ্ট করে তুলেছে:

int main()
{
    int num = 2;
    Variable var(num);  // If equivalent to Variable<int> var(num),
    Variable var2(var); //Variable<int> or Variable<Variable<int>> ?
}

আরেকটি ভাল পয়েন্ট। ধরে নেওয়া যায় যে এখানে কোনও অনুলিপি নির্ধারিত ভেরিয়েবল (ভেরিয়েবল <obj> ডি) সংজ্ঞায়িত রয়েছে, সেখানে কোনও একরকম নজির প্রতিষ্ঠিত হতে হবে।
জিআরবি

1
অথবা, বিকল্প হিসাবে, সংকলকটি আবার কোনও অপরিজ্ঞাত টেম্পলেট প্যারামিটার ত্রুটি ফেলে দিতে পারে, যেমনটি আমি পাইটিসের উত্তরের সাথে পরামর্শ দিয়েছিলাম। তবে, আপনি যদি এই রাস্তাটি নিয়ে যান, সমস্যাগুলি (ত্রুটি) ছাড়াই অনুমান সংঘটিত হওয়ার পরিমাণটি আরও ছোট হয়ে চলেছে।
জিআরবি

এটি আসলে একটি আকর্ষণীয় বিষয় এবং (যেমনটি আমি আমার উত্তরে উল্লেখ করেছি) আমি এখনও নিশ্চিত নই যে গৃহীত সি ++ 17 প্রস্তাবটি কীভাবে এটি সমাধান করে।
কাইল স্ট্র্যান্ড

9

মনে করি যে সংকলকটি যা আপনাকে জিজ্ঞাসা করেছে সেটিকে সমর্থন করে। তাহলে এই কোডটি বৈধ:

Variable v1( 10); // Variable<int>

// Some code here

Variable v2( 20.4); // Variable<double>

এখন, দুটি ভিন্ন ধরণের (ভেরিয়েবল এবং ভেরিয়েবল) কোডে আমার একই ধরণের নাম (ভেরিয়েবল) রয়েছে। আমার বিষয়ভিত্তিক দৃষ্টিকোণ থেকে, এটি কোডের পঠনযোগ্যতাকে বেশ প্রভাবিত করে। একই নেমস্পেসে দুটি ভিন্ন ধরণের জন্য একই ধরণের নাম থাকা আমার কাছে বিভ্রান্তিকর বলে মনে হচ্ছে।

পরবর্তী আপডেট: আরও একটি বিষয় বিবেচনা করুন: আংশিক (বা পূর্ণ) টেম্পলেট বিশেষীকরণ।

আমি যদি ভেরিয়েবলকে বিশেষজ্ঞ করি এবং আপনার প্রত্যাশা মতো কোনও নির্মাণকারীর সরবরাহ না করে তবে কী হবে?

সুতরাং আমি হবে:

template<>
class Variable<int>
{
// Provide default constructor only.
};

তারপরে আমার কাছে কোডটি রয়েছে:

Variable v( 10);

সংকলকটি কী করবে? এটি পরিবর্তনশীল যে অনুমিত করতে জেনেরিক পরিবর্তনশীল শ্রেণির সংজ্ঞাটি ব্যবহার করুন, তারপরে আবিষ্কার করুন যে ভেরিয়েবল একটি প্যারামিটার কনস্ট্রাক্টর সরবরাহ করে না?


1
আরও খারাপ: আপনার যদি কেবল পরিবর্তনশীল <int> :: পরিবর্তনশীল (ভাসমান) থাকে তবে কী হবে? আপনার কাছে এখন ভেরিয়েবল (1f) ছাড় করার দুটি উপায় এবং ভেরিয়েবল (1) কে ছাড় করার কোনও উপায় নেই।
MSalters

এটি একটি ভাল পয়েন্ট, তবে কাস্টিং দ্বারা সহজেই ছাড়িয়ে যেতে পারে: ভেরিয়েবল ভি 1 ((ডাবল) 10)
jpinto3912

আমি সম্মত হই যে কোড পঠনযোগ্যতা একটি বিষয়গত সমস্যা, তবে, আপনি টেম্পলেট বিশেষায়নের বিষয়ে যা বলছেন তার সাথে আমি 100% সম্মত। সমাধানটি সম্ভবত একটি অপরিজ্ঞাত টেম্পলেট প্যারামিটার ত্রুটি প্রদান করা হবে (একবার সংকলক <<> বিশেষায়নের দিকে তাকান এবং কোনও বৈধ নির্মাতা দেখতে না পান, এটির বলে যে আপনি কোন টেম্পলেটটি ব্যবহার করতে চান তার কোনও ধারণা নেই এবং আপনাকে অবশ্যই স্পষ্টভাবে নির্দিষ্ট করতে হবে) তবে আমি সম্মত হই যে এটি কোনও সুন্দর সমাধান নয়। আমি এটিকে আরও একটি বড় সিনট্যাকটিক গর্ত হিসাবে যুক্ত করব যা মোকাবেলা করার প্রয়োজন হবে (তবে পরিণতি যদি কেউ গ্রহণ করে তবে সমাধান করা যেতে পারে)।
জিআরবি

4
@ jpinto3912 - আপনি পয়েন্টটি মিস করছেন। সংকলকটিকে সমস্ত সম্ভাব্য ভেরিয়েবল <টি> এর তদন্ত করতে হবে যে কোনও সিটি ভেরিয়েবল <T> :: ভেরিয়েবল একটি দ্বিধাগ্রস্থ কর্টর সরবরাহ করে কিনা তা পরীক্ষা করতে। অস্পষ্টতা থেকে মুক্তি পাওয়া সমস্যা নয় - সাধারণ তাত্ক্ষণিক পরিবর্তনশীল <ডাবল> আপনি যদি চান তবে এটি নিজেরাই করুন। এটি প্রথমে সেই অস্পষ্টতা খুঁজে পেয়েছে যা এটি অসম্ভব করে তোলে।
MSalters

6

সি ++ 03 এবং সি ++ 11 স্ট্যান্ডার্ড কনস্ট্যুরেক্টরকে দেওয়া প্যারামিটারগুলি থেকে টেমপ্লেট আর্গুমেন্ট ছাড়ের অনুমতি দেয় না।

তবে "কনস্ট্রাক্টরগুলির জন্য টেম্পলেট প্যারামিটার ছাড়ের" জন্য একটি প্রস্তাব রয়েছে যাতে আপনি শীঘ্রই যা চাইছেন তা পেতে পারেন। সম্পাদনা: প্রকৃতপক্ষে, এই বৈশিষ্ট্যটি C ++ 17 এর জন্য নিশ্চিত করা হয়েছে।

দেখুন: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3602.html এবং http://www.open-std.org/jtc1/sc22/wg21/docs/ কাগজপত্র / 2015 / p0091r0.html


বৈশিষ্ট্যটি সি ++ 17 এ যুক্ত করা হয়েছে, তবে "শীঘ্রই" 6 থেকে 8 বছরের সময়সীমার ফ্রেমের ক্ষেত্রে প্রযোজ্য তা যদি হয় না। ;)
চিটস

2

অনেকগুলি ক্লাস কন্সট্রাক্টর পরামিতিগুলির উপর নির্ভর করে না। কেবলমাত্র কয়েকটি শ্রেণীর মধ্যে কেবলমাত্র একজন নির্মাণকারী রয়েছে এবং এই নির্মাণকারীর ধরণের (গুলি) এর উপর ভিত্তি করে প্যারামিটারাইজ করা হয়।

আপনার যদি সত্যিই টেমপ্লেট অনুমিতের প্রয়োজন হয় তবে একটি সহায়ক ফাংশন ব্যবহার করুন:

template<typename obj>
class Variable 
{
      obj data;
public: 
      Variable(obj d)
      : data(d)
      { }
};

template<typename obj>
inline Variable<obj> makeVariable(const obj& d)
{
    return Variable<obj>(d);
}

1
অবশ্যই এই কার্যকারিতাটি কেবল কিছু শ্রেণির জন্য কার্যকর প্রমাণিত হবে তবে ফাংশন অনুমানের জন্য একই কথা বলা যেতে পারে। সমস্ত টেম্পলেটেড ক্রিয়াকলাপগুলি যুক্তি তালিকা থেকে তাদের পরামিতিগুলি নেয় না, তবুও আমরা সেই ফাংশনগুলির জন্য অনুমানের অনুমতি দিই।
জিআরবি

1

প্রকারের হ্রাস বর্তমান সি ++ তে টেম্পলেট ফাংশনগুলির মধ্যে সীমাবদ্ধ তবে এটি অনেক আগে থেকেই উপলব্ধি হয়ে গেছে যে অন্যান্য প্রসঙ্গে প্রকারভেদে টাইপ ছাড় খুব কার্যকর হবে। সুতরাং সি ++ 0 এক্স এর auto

যদিও ঠিক কি আপনি সুপারিশ সি ++ 0x মধ্যে সম্ভব হবে না, নিম্নলিখিত শো আপনি চমত্কার বন্ধ পেতে পারেন:

template <class X>
Variable<typename std::remove_reference<X>::type> MakeVariable(X&& x)
{
    // remove reference required for the case that x is an lvalue
    return Variable<typename std::remove_reference<X>::type>(std::forward(x));
}

void test()
{
    auto v = MakeVariable(2); // v is of type Variable<int>
}

0

আপনি ঠিক বলেছেন যে সংকলকটি সহজেই অনুমান করতে পারে, তবে এটি যতটা আমি জানি ঠিক তেমন স্ট্যান্ডার্ড বা সি ++ 0x এ নেই তাই কমপায়ার সরবরাহকারীরা এই বৈশিষ্ট্যটি যুক্ত করার আগে আপনাকে কমপক্ষে আরও 10 বছর (আইএসও স্ট্যান্ডার্ড নির্ধারিত হারের হার ঘুরে) অপেক্ষা করতে হবে


এটি আসন্ন স্ট্যান্ডার্ডের সাথে সঠিক নয় একটি অটো কীওয়ার্ড চালু করা হবে। এই থ্রেডে জেমস হপকিন্সের পোস্টটি একবার দেখুন। stackoverflow.com/questions/984394/… । তিনি দেখান যে এটি সি ++ 0 এক্স-এ কীভাবে সম্ভব হবে।
ওভেনস

1
কেবল নিজেকে সংশোধন করার জন্য, অটো কীওয়ার্ডটি বর্তমান মানকটিতেও উপস্থিত রয়েছে, তবে ভিন্ন উদ্দেশ্যে।
ওভেনস

দেখে মনে হচ্ছে এটি 8 বছর হবে (এই উত্তরের সময় থেকে) ... সুতরাং 10 বছর খারাপ ধারণা ছিল না, যদিও গড় সময়ে দুটি মান রয়েছে!
কাইল স্ট্র্যান্ড

-1

আসুন সমস্যাটি একটি শ্রেণীর রেফারেন্সের সাথে দেখি প্রত্যেকের সাথে স্ট্যান্ড :: ভেক্টর দিয়ে ফ্যামিলার হওয়া উচিত।

প্রথমত, ভেক্টরের খুব সাধারণ ব্যবহার এমন কনস্ট্রাক্টর ব্যবহার করা হয় যা কোনও পরামিতি নেয় না:

vector <int> v;

এই ক্ষেত্রে, স্পষ্টতই কোনও অনুমান করা যায় না।

একটি দ্বিতীয় সাধারণ ব্যবহার একটি প্রাক আকারের ভেক্টর তৈরি করা:

vector <string> v(100);

এখানে, যদি অনুমান ব্যবহার করা হত:

vector v(100);

আমরা স্ট্রস নয়, অন্তরগুলির একটি ভেক্টর পেয়েছি এবং সম্ভবত এটি আকারের নয়!

অবশেষে, এমন কনস্ট্রাক্টরগুলি বিবেচনা করুন যা একাধিক পরামিতি নেয় - "অনুমান" সহ:

vector v( 100, foobar() );      // foobar is some class

অনুমানের জন্য কোন পরামিতি ব্যবহার করা উচিত? আমাদের সংকলকটি বলার কিছু উপায় প্রয়োজন যে এটি দ্বিতীয় হওয়া উচিত।

কোনও শ্রেণীর জন্য ভেক্টরের মতো সাধারণ এই সমস্যাগুলির সাথে, অনুমান কেন ব্যবহার করা হচ্ছে না তা সহজেই দেখা যায়।


3
আমি মনে করি আপনি ধারণাটি ভুল বুঝছেন। নির্মাণকারীদের জন্য প্রকারের অনুক্রম কেবল তখনই ঘটতে পারে যদি টেম্পলেট প্রকারটি নির্মাণকারীর অংশ হয়। ধরে নিন যে ভেক্টরের টেম্পলেট সংজ্ঞা টেম্পলেট রয়েছে <টাইপনেম টি>। আপনার উদাহরণটি কোনও সমস্যা নয় কারণ ভেক্টরের নির্মাতাকে ভেক্টর (ইনট আকার) হিসাবে সংজ্ঞায়িত করা হবে, ভেক্টর (টি আকার) নয়। কেবল ভেক্টরের ক্ষেত্রে (টি আকার) কোনও অনুমান ঘটতে পারে; প্রথম উদাহরণে, সংকলক টি ত্রুটিযুক্ত নয় এমনটি বলে একটি ত্রুটি দেবে। ফাংশন টেমপ্লেট অনুমিতি কীভাবে কাজ করে তাগতভাবে অভিন্ন।
জিআরবি

সুতরাং এটি কেবল এমন একমাত্র নির্মাণকারীদের জন্য স্থান গ্রহণ করবে যেখানে একটি একক প্যারামিটার রয়েছে এবং যেখানে সেই পরামিতিটি একটি টেম্পলেট প্যারামিটারের ধরন? এটি খুব অল্প সংখ্যক উদাহরণ বলে মনে হচ্ছে।

এটি অগত্যা একক প্যারামিটার হওয়ার দরকার নেই। উদাহরণস্বরূপ, কারও কাছে ভেক্টরের ভেক্টর কনস্ট্রাক্টর থাকতে পারে (ইনট সাইজ, টি ফার্স্ট এলিমেন্ট)। যদি কোনও টেমপ্লেটের একাধিক প্যারামিটার থাকে (টেমপ্লেট <টাইপনেম টি, টাইপনাম ইউ>) থাকে তবে একটির কাছে ধারক :: ধারক থাকতে পারে (টি ফার্স্টবজেক্ট, ইউ সেকেন্ডওজেক্ট)। যদি কোনও টেমপ্লেটের একাধিক প্যারামিটার থাকে তবে কনস্ট্রাক্টর কেবল সেগুলির একটি গ্রহণ করে, যেমন হোল্ডার (ইউ সেকেন্ডবজেক্ট), তবে টি সর্বদা স্পষ্টভাবে বিবৃত করতে হবে। নিয়মগুলি যতটা সম্ভব ফাংশন টেম্পলেট অনুকরণের অনুরূপ হিসাবে অভিযুক্ত করা হবে।
জিআরবি

-2

কর্টরটিকে একটি টেমপ্লেট তৈরি করে ভেরিয়েবলের কেবল একটির ফর্ম থাকতে পারে তবে বিভিন্ন সিটার থাকতে পারে:

class Variable {
      obj data; // let the compiler guess
      public:
      template<typename obj>
      Variable(obj d)
       {
           data = d;
       }
};

int main()
{
    int num = 2;
    Variable var(num);  // Variable::data int?

    float num2 = 2.0f;
    Variable var2(num2);  // Variable::data float?
    return 0;         
}

দেখা? আমাদের একাধিক চলক :: ডেটা সদস্য থাকতে পারে না।


এটি কোনও দৃশ্যের আওতায় আসবে না। বস্তু ডেটা বিবেচনায় ডেটা অপরিজ্ঞাত হয় যেহেতু সেই শ্রেণিটি আর কোনও টেম্পলেট নয়। এই জাতীয় কোড যে কোনওভাবেই অবৈধ হবে।
জিআরবি

আপনার বর্ণিত সংকলক আচরণটি আমি চেয়েছিলাম, সুতরাং সেই সীমাবদ্ধতাটি (আমার ক্ষেত্রে) বাইপাস করার একটি উপায় আমি খুঁজে বের করেছি, যা আপনি আকর্ষণীয়, স্ট্যাকওভারফ্লো.com
নিক দানডৌলাকিস

-2

এটি সম্পর্কে আরও তথ্যের জন্য সি ++ টেম্পলেট আর্গুমেন্ট ছাড় See


4
আমি এই নিবন্ধটি আগে পড়েছি এবং আমি যা বলছি সে সম্পর্কে খুব বেশি কথা বলে মনে হচ্ছে না। লেখক যখন ক্লাসের সাথে যুক্তি ছাড়ের বিষয়ে কথা বলছেন কেবল তখনই যখন তিনি বলেন যে এটি নিবন্ধের শীর্ষে করা যাবে না;) - আপনি যে বিভাগগুলি প্রাসঙ্গিক বলে মনে করেন তা যদি আমি উল্লেখ করতে পারি তবে আমি ' ডি সত্যিই প্রশংসা করি।
জিআরবি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.