টেম্পলেটেড ক্লাস থেকে একক পদ্ধতির টেম্পলেট বিশেষীকরণ


92

সর্বদা বিবেচনা করে নিন যে আমার শৃঙ্খলাবদ্ধ শ্রেণি সহ নিম্নলিখিত শিরোনামটি কমপক্ষে দুটি .CPPফাইলে অন্তর্ভুক্ত রয়েছে , এই কোডটি সঠিকভাবে সংকলন করেছে:

template <class T>
class TClass 
{
public:
  void doSomething(std::vector<T> * v);
};

template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
  // Do something with a vector of a generic T
}

template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
  // Do something with a vector of int's
}

তবে বিশেষায়নের পদ্ধতিতে ইনলাইনটি নোট করুন। পদ্ধতিটিকে আরও একবার সংজ্ঞায়িত করার কারণে এটি কোনও লিঙ্কার ত্রুটি এড়ানো প্রয়োজন (ভিএস ২০০৮ এ এলএনকে ২০০৫)। আমি এটি বুঝতে পারি কারণ আফাইক একটি সম্পূর্ণ টেম্পলেট বিশেষীকরণ একটি সাধারণ পদ্ধতির সংজ্ঞা হিসাবে একই।

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

ধন্যবাদ!


4
আপনি কেন ইনলাইন সরাতে চান? আপনি কি এটিকে নান্দনিকভাবে অপছন্দনীয় মনে করেন? আপনি কি মনে করেন এটি আপনার কোডটির অর্থ পরিবর্তন করে?
মার্টিন ইয়র্ক

4
কারণ এই পদ্ধতিটি যদি "দীর্ঘ" হয় এবং অনেক জায়গায় ব্যবহৃত হয় তবে আমি এর বাইনারি কোডটি সর্বত্র অনুলিপি করে পেয়েছি, তাই না? আমি এ প্রশ্নের ব্যাখ্যা দেওয়ার চেষ্টা করেছি তবে আমার ধারণা এটি পরিষ্কার ছিল না ... :)
চুইম

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

উত্তর:


72

সাধারণ ফাংশন হিসাবে আপনি ঘোষণা এবং বাস্তবায়ন ব্যবহার করতে পারেন। আপনার শিরোনামের ঘোষণাটি দিন:

template <>
void TClass<int>::doSomething(std::vector<int> * v);

এবং আপনার সিপিপি-ফাইলগুলির মধ্যে একটিতে প্রয়োগ স্থাপন করুন:

template <>
void TClass<int>::doSomething(std::vector<int> * v) {
 // Do somtehing with a vector of int's
}

ইনলাইন অপসারণ করতে ভুলবেন না (আমি ভুলে গিয়েছিলাম এবং ভেবেছিলাম এই সমাধানটি কার্যকর হবে না :))। ভিসি ++ 2005 এ চেক করা হয়েছে


আমি এর আগেও এর চেয়ে কম কিছু অনুরূপ চেষ্টা করেছি তবে আমি অন্যান্য ত্রুটি পেয়েছি তবে এখন আপনি উল্লেখ করেছেন আমি অবশ্যই inlineঅনুলিপি / আটকানোর সময় অপসারণ করতে ভুলে গিয়েছিলাম । এভাবে কাজ!
চুইম

একইটি টেমপ্লেট ফ্রি ফাংশনগুলিতে প্রযোজ্য (শ্রেণিবদ্ধের বিপরীতে)। আমার ফাংশন বিশেষায়নের জন্য আমি একই লিঙ্কারের ত্রুটি পেয়েছিলাম। আমি ফাংশন স্পেশালাইজেশনের বডিটিকে একটি .cpp ফাইলে স্থানান্তরিত করেছি এবং বিশেষায়নের ঘোষণাকে শিরোনামে রেখে দিয়েছি এবং সমস্ত কিছু কাজ করেছে। ধন্যবাদ!
aldo

আমি কেবল এই সমস্যার মধ্যে দৌড়েছি এবং উপরেরগুলি এটি আমার জন্য সমাধান করেছে। অতিরিক্তভাবে, সংকলকটি টেম্পলেট কোডটি প্রসারিত করে সেদিকে আপনার যত্ন নেওয়া দরকার । এটি যদি দুইবার করা হয় তবে সংকলক একাধিক সংজ্ঞা নিয়ে অভিযোগ করে।
ডিয়েডেরিক

4

আপনার বিশেষায়িত সংজ্ঞাটি সিপিপি ফাইলে স্থানান্তরিত করতে হবে। ফাংশনটি টেম্পলেট হিসাবে ঘোষিত না করা সত্ত্বেও টেমপ্লেট শ্রেণির সদস্য ফাংশন বিশেষায়িত করার অনুমতি দেওয়া হয়।


3

মূলশব্দটি ইনলাইন সরানোর কোনও কারণ নেই।
এটি যাইহোক কোডের অর্থ পরিবর্তন করে না।


প্রশ্নের মন্তব্য থেকে অনুলিপি করা হয়েছে: কারণ যদি এই পদ্ধতিটি "দীর্ঘ" হয় এবং অনেক জায়গায় ব্যবহৃত হয় তবে আমি এর বাইনারি কোডটি সর্বত্র অনুলিপি করে পেয়েছি, তাই না? আমি প্রশ্নের মধ্যে এটি ব্যাখ্যা করার চেষ্টা করেছি তবে আমার ধারণা এটি পরিষ্কার ছিল না ... :)
চুইম

4
লিঙ্কার কোনও অতিরিক্ত অনুলিপি সরিয়ে দেয়। সুতরাং একটি অ্যাপ্লিকেশন বা lib এর মধ্যে আপনার কাছে কেবল একবার পদ্ধতির উদাহরণ থাকবে।
মার্টিন ইয়র্ক

4
যদি inlineকার্যটির কীওয়ার্ডের ফলাফলটি প্রকৃতপক্ষে অন্তর্ভুক্ত থাকে (মানকটি বলে যে সংকলকটি এটি একটি ইঙ্গিত হিসাবে নেওয়া উচিত), তবে সেই অতিরিক্ত অনুলিপিগুলি সরানো যাবে না। তবে, এটি কেবল ইনলাইন করার ইঙ্গিত (এটির প্রাথমিক প্রভাবটি "নির্দিষ্ট উপায়ে লিঙ্কের সংঘর্ষে ত্রুটিগুলি উত্পন্ন করবেন না" বলতে হবে)
ইয়াক্ক - অ্যাডাম নেভ্রামাউন্ট

2

আপনি যদি কোনও কারণে ইনলাইনটি সরাতে চান তবে ম্যাক্সিমাম 1000 এর সমাধানটি পুরোপুরি বৈধ।

আপনার মন্তব্যে, যদিও মনে হয় আপনি বিশ্বাস করেন যে ইনলাইন কীওয়ার্ডের অর্থ তার সমস্ত বিষয়বস্তু সহ ফাংশনটি সর্বদা অন্তর্ভুক্ত হয়ে যায় তবে আফাইক যা আপনার সংকলক অপ্টিমাইজেশনের উপর নির্ভর করে very

সি ++ এফএকিউ থেকে উদ্ধৃতি দেওয়া হচ্ছে

কোনও ফাংশনটি ইনলাইন হিসাবে নির্দিষ্ট করার বিভিন্ন উপায় রয়েছে যার মধ্যে কয়েকটি ইনলাইন কীওয়ার্ডকে জড়িত করে, অন্যরা তা করে না। আপনি কোনও ফাংশনটিকে ইনলাইন হিসাবে কীভাবে নির্ধারণ করেন তা বিবেচনা না করেই, এটি অনুরোধ যে সংকলকটি এড়িয়ে যাওয়ার অনুমতি দেওয়া হয়েছে: সংকলকটি কিছু অংশ, সমস্ত, বা যে কোনও জায়গাকে আপনি ইনলাইন হিসাবে মনোনীত স্থানে কল করেছেন সেগুলির কোনওটি ইনলাইন-প্রসারিত করতে পারে। (যদি এটি আশাহীনভাবে অস্পষ্ট বলে মনে হয় তবে হতাশ হবেন না the উপরের নমনীয়তাটি একটি বিশাল সুবিধা it এটি কম্পাইলারটি ছোট ফাংশনগুলির থেকে বড় ফাংশনগুলিকে আলাদাভাবে আচরণ করতে দেয়, এবং এটি সংকলক কোডটি উত্পন্ন করতে দেয় যা আপনি যদি নির্বাচন করেন তবে ডিবাগ করা সহজ gene সঠিক সংকলক বিকল্প।)

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


1

আমি যুক্ত করতে চাই যে inlineশিরোনাম ফাইলটিতে বিশেষত্বও রেখে যাওয়ার ইচ্ছা থাকলে কীওয়ার্ডটি সেখানে রাখার এখনও একটি ভাল কারণ আছে।

"স্বজ্ঞাতভাবে, আপনি যখন কোনও কিছু পুরোপুরি বিশেষজ্ঞ করে তোলেন, এটি আর কোনও টেম্পলেট প্যারামিটারের উপর নির্ভর করে না - সুতরাং আপনি যদি বিশেষীকরণটিকে ইনলাইন না করেন তবে আপনাকে এটি .h এর পরিবর্তে একটি .cpp ফাইলে রাখা দরকার বা আপনি লঙ্ঘন শেষ করেন একটি সংজ্ঞা নিয়ম ... "

তথ্যসূত্র: https://stackoverflow.com/a/4445772/1294184


0

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

আমার পরিস্থিতি ওপি-র তুলনায় কিছুটা আলাদা (তবে এই উত্তরটি আমি মনে করি এটি ছেড়ে দেওয়ার পক্ষে যথেষ্ট) মূলত, আমি "স্ট্যাটাসের ধরণগুলি" সংজ্ঞায়িত করে বিভিন্ন ধরণের শ্রেণির সাথে একটি তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করছি। এই ধরণের হৃদয় কেবল enumসরল, তবে ক্লাসগুলি সমস্ত সাধারণ (বিমূর্ত) পিতামাতার কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয় এবং বিভিন্ন ইউটিলিটি ফাংশন সরবরাহ করে যেমন অপারেটর ওভারলোডিং এবং একটি static toString(enum type)ফাংশন। প্রতিটি স্ট্যাটাস enumএকে অপরের থেকে আলাদা এবং সম্পর্কিত নয়। উদাহরণস্বরূপ, একটিতে enumক্ষেত্র রয়েছে NORMAL, DEGRADED, INOPERABLE, অন্যের রয়েছে AVAILBLE, PENDING, MISSINGইত্যাদি My আমার সফ্টওয়্যারটিতে বিভিন্ন উপাদানগুলির জন্য বিভিন্ন ধরণের স্ট্যাটাস পরিচালনা করার দায়িত্বে থাকে। এটি এলো যে আমি toStringএইগুলির জন্য ফাংশনগুলি ব্যবহার করতে চাইenumক্লাস, কিন্তু যেহেতু তারা বিমূর্ত, আমি তাদের সরাসরি ইনস্ট্যান্ট করতে পারিনি। আমি যে ক্লাসটি ব্যবহার করতে চাইছিলাম তা আমি বাড়িয়ে দিতে পারতাম, তবে শেষ পর্যন্ত আমি একটি templateক্লাস তৈরির সিদ্ধান্ত নিয়েছিলাম , যেখানে আমি যতটা typenameকংক্রিট স্ট্যাটাসের enumযত্ন নিই তা হবে । সম্ভবত এই সিদ্ধান্ত সম্পর্কে কিছু বিতর্ক হতে পারে, তবে আমি অনুভব করেছি যে এটি enumআমার নিজস্ব কাস্টমটির সাথে প্রতিটি বিমূর্ত শ্রেণিকে বাড়ানো এবং বিমূর্ত ফাংশনগুলি বাস্তবায়নের চেয়ে অনেক কম কাজ ছিল । এবং অবশ্যই আমার কোডে, আমি কেবল কল করতে সক্ষম হতে চেয়েছি .toString(enum type)এবং এটির স্ট্রিং উপস্থাপনা মুদ্রণ করতে চাই enum। যেহেতু সমস্ত enumগুলি সম্পূর্ণরূপে সম্পর্কিত নয়, সেগুলির প্রতিটি নিজস্ব ছিল owntoStringফাংশনগুলি (কিছু গবেষণার পরে আমি শিখেছি) টেমপ্লেট বিশেষায়নের সাহায্যে কল করতে হয়েছিল। আমাকে এখানে নিয়ে গেছে এই কাজটি সঠিকভাবে করার জন্য আমার কী করতে হয়েছিল তার একটি এমসিভিই নীচে। এবং আসলে আমার সমাধান @ ম্যাক্সিম 1000 এর চেয়ে কিছুটা আলাদা ছিল।

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

// file enums.h
#include <string>

class Enum1
{
public:
  enum EnumerationItem
  {
    BEARS1,
    BEARS2,
    BEARS3
  };

  static std::string toString(EnumerationItem e)
  {
    // code for converting e to its string representation,
    // omitted for brevity
  }
};

class Enum2
{
public:
  enum EnumerationItem
  {
    TIGERS1,
    TIGERS2,
    TIGERS3
  };

  static std::string toString(EnumerationItem e)
  {
    // code for converting e to its string representation,
    // omitted for brevity
  }
};

পরবর্তী ফাইলটি একটি ভিন্ন কোড ব্লকে পৃথক করতে এই লাইনটি যুক্ত করা:

// file TemplateExample.h
#include <string>

template <typename T>
class TemplateExample
{
public:
  TemplateExample(T t);
  virtual ~TemplateExample();

  // this is the function I was most concerned about. Unlike @maxim1000's
  // answer where (s)he declared it outside the class with full template
  // parameters, I was able to keep mine declared in the class just like
  // this
  std::string toString();

private:
  T type_;
};

template <typename T>
TemplateExample<T>::TemplateExample(T t)
  : type_(t)
{

}

template <typename T>
TemplateExample<T>::~TemplateExample()
{

}

পরবর্তী ফাইল

// file TemplateExample.cpp
#include <string>

#include "enums.h"
#include "TemplateExample.h"

// for each enum type, I specify a different toString method, and the
// correct one gets called when I call it on that type.
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
  return Enum1::toString(type_);
}

template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
  return Enum2::toString(type_);
}

পরবর্তী ফাইল

// and finally, main.cpp
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"

int main()
{
  TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
  TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);

  std::cout << t1.toString() << std::endl;
  std::cout << t2.toString() << std::endl;

  return 0;
}

এবং এই ফলাফলগুলি:

BEARS1
TIGERS3

এটি আমার সমস্যা সমাধানের আদর্শ সমাধান হলে কোনও ক্লু নেই, তবে এটি আমার পক্ষে কাজ করেছে। এখন, আমি গণনার কতগুলি প্রকার toStringব্যবহার করেই শেষ করি না কেন, আমাকে কেবলমাত্র .cpp ফাইলে পদ্ধতিটির জন্য কয়েকটি লাইন যুক্ত করতে হবে এবং আমি নিজেরাই toStringপ্রয়োগ না করে এবং প্রতিটি প্রসারিত না করেই ইতিমধ্যে নির্ধারিত লাইব্রেরিগুলি ব্যবহার করতে পারি enumক্লাস আমি ব্যবহার করতে চাই।

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