সি ++ এ অভ্যন্তরীণ টাইপডেফগুলি - ভাল স্টাইল বা খারাপ শৈলী?


179

আমি ইদানীং নিজেকে প্রায়শই কিছু করতে দেখেছি টাইপডিফগুলি শ্রেণীর অভ্যন্তরে কোনও নির্দিষ্ট শ্রেণীর সাথে সম্পর্কিত বলে ঘোষণা করা

class Lorem
{
    typedef boost::shared_ptr<Lorem> ptr;
    typedef std::vector<Lorem::ptr>  vector;

//
// ...
//
};

এই ধরণেরগুলি তখন কোডের অন্যত্র ব্যবহৃত হয়:

Lorem::vector lorems;
Lorem::ptr    lorem( new Lorem() );

lorems.push_back( lorem );

কারণগুলি আমি এটি পছন্দ করি:

  • এটা তোলে, গোলমাল বর্গ টেমপ্লেট চালু হ্রাস std::vector<Lorem>হয়ে Lorem::vector, ইত্যাদি
  • এটি অভিপ্রায় হিসাবে একটি বিবৃতি হিসাবে কাজ করে - উপরের উদাহরণে, লরেম ক্লাসটি boost::shared_ptrএকটি ভেক্টরের মাধ্যমে গণনা করা এবং সঞ্চিত রেফারেন্স হিসাবে বিবেচিত ।
  • এটি বাস্তবায়নের পরিবর্তনের অনুমতি দেয় - অর্থাত্ যদি boost::intrusive_ptrপরবর্তী পর্যায়ে যদি লোরেমকে গোপনীয়ভাবে রেফারেন্স গণনা করা হয় (মাধ্যমে ) করা হয় তবে কোডটিতে এটির সর্বনিম্ন প্রভাব পড়তে পারে।
  • আমি মনে করি এটি 'সুন্দর' দেখাচ্ছে এবং এটি পড়ার পক্ষে যুক্তিযুক্তভাবে সহজ।

আমার পছন্দ না হওয়ার কারণগুলি:

  • কখনও কখনও নির্ভরতা নিয়ে সমস্যা থাকে - আপনি যদি এম্বেড করতে চান, বলুন, Lorem::vectorঅন্য শ্রেণীর মধ্যে একটি তবে কেবল লোরেমকে ঘোষণা করতে (বা তার শিরোনামের ফাইলে নির্ভরতা প্রবর্তনের বিরোধিতা হিসাবে) প্রয়োজন হবে তবে আপনাকে শেষ পর্যন্ত ব্যবহার করতে হবে সুস্পষ্ট ধরণের (যেমন boost::shared_ptr<Lorem>তুলনায় বরং Lorem::ptr) যা কিছুটা বেমানান।
  • এটি খুব সাধারণ নাও হতে পারে, এবং তাই বোঝা শক্ত?

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

উত্তর:


153

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


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

1
ওয়েল স্ট্যান্ডার্ড লাইব্রেরি ক্লাসের চেয়ে টেমপ্লেট দিয়ে তৈরি, তবে আমি মনে করি যে উভয়ের পক্ষে ন্যায়সঙ্গতটি একই রকম।

14

এটি অভিপ্রায় হিসাবে একটি বিবৃতি হিসাবে কাজ করে - উপরের উদাহরণে, লরেম ক্লাসটি বুস্ট :: শেয়ার্ড_প্ট্রের মাধ্যমে গণ্য করা হয়েছে এবং একটি ভেক্টরে সঞ্চিত রয়েছে।

এটি ঠিক এটি করে না

আমি যদি কোডটিতে 'ফু :: পিটিআর' দেখি তবে আমার কোনও ধারণা নেই যে এটি কোনও শেয়ারড_পিটার বা একটি ফু * (এসটিএল :: :: পয়েন্টার টাইপডেফ যে টি *, মনে আছে) বা যাই হোক না কেন। ESP। যদি এটি ভাগ করে নেওয়া পয়েন্টার হয় তবে আমি মোটেও টাইপডেফ সরবরাহ করি না, তবে শেয়ারড_প্টারকে কোডটিতে স্পষ্টভাবে ব্যবহার রাখি।

প্রকৃতপক্ষে, আমি টেম্পলেট মেটাপ্রগ্রামের বাইরে খুব কমই টাইপিডফ ব্যবহার করি।

এসটিএল সর্বদা এই ধরণের জিনিস করে does

সদস্য ফাংশন এবং নেস্টেড টাইপিডফগুলির ক্ষেত্রে সংজ্ঞায়িত ধারণার সাথে এসটিএল নকশাটি একটি historicalতিহাসিক কাল-ডি-স্যাক, আধুনিক টেম্পলেট লাইব্রেরিগুলি ফ্রি ফাংশন এবং বৈশিষ্ট্য শ্রেণি (সিএফ। বুস্ট.গ্রাফ) ব্যবহার করে, কারণ এগুলি অন্তর্নির্মিত প্রকারগুলি বাদ দেয় না ধারণাটির মডেলিং করা এবং কারণ এটি এমন মানিয়ে যাওয়া প্রকারগুলি তৈরি করে যা প্রদত্ত টেমপ্লেট লাইব্রেরিগুলির ধারণাগুলি সহজ মনে রাখে না।

একই ভুল করার কারণ হিসাবে এসটিএল ব্যবহার করবেন না।


আমি আপনার প্রথম অংশের সাথে একমত, তবে আপনার সাম্প্রতিক সম্পাদনাটি একটু সংক্ষিপ্ত দৃষ্টিতে। এই জাতীয় নেস্টেড ধরণের বৈশিষ্ট্য শ্রেণীর সংজ্ঞা সহজতর করে, কারণ তারা একটি বুদ্ধিমান ডিফল্ট সরবরাহ করে। নতুন std::allocator_traits<Alloc>শ্রেণীর কথা বিবেচনা করুন ... আপনার লেখার প্রতিটি একক বরাদ্দকারীর জন্য আপনাকে এটি বিশেষীকরণ করতে হবে না, কারণ এটি সরাসরি প্রকারগুলি থেকে ধার করে Alloc
ডেনিস জিকিফুজ

@ ডেনিস: সি ++ এ সুবিধার্থে কোনও গ্রন্থাগারের / ব্যবহারকারীর / পাশে থাকা উচিত, তার লেখক / লেখকের পাশে নয়: ব্যবহারকারী কোনও বৈশিষ্ট্যের জন্য অভিন্ন ইন্টারফেস চান এবং কেবল একটি বৈশিষ্ট্যযুক্ত শ্রেণি তা ​​দিতে পারে, কারণ উপরে বর্ণিত)। তবে এমনকি একজন Allocলেখক হিসাবে , std::allocator_traits<>প্রয়োজনীয় টাইপডেফগুলি যুক্ত করার চেয়ে তার নতুন ধরণের জন্য বিশেষীকরণ করা ঠিক তেমন শক্ত নয় । আমি উত্তরটি সম্পাদনা করেছি, কারণ আমার পুরো উত্তরটি কোনও মন্তব্যে মাপসই হয় না।
মার্ক মুটজ - মিমুতজ

কিন্তু এটা হয় ব্যবহারকারী পাশ। হিসেবে ব্যবহারকারী এর allocator_traitsএকটি কাস্টম বরাদ্দকরণ তৈরি করতে প্রয়াস, আমি বৈশিষ্ট্যগুলো ক্লাসের পনের সদস্যদের সঙ্গে বিরক্ত করার জন্য আছে না ... আমি যা করতে হবে বলে হয় typedef Blah value_type;এবং উপযুক্ত সদস্য ফাংশন প্রদান এবং ডিফল্ট allocator_traitsজিনিসটা হবে বিশ্রাম. আরও, বুস্ট.গ্রাফের আপনার উদাহরণটি দেখুন। হ্যাঁ, এটি বৈশিষ্ট্য শ্রেণীর অত্যধিক ব্যবহার করে ... তবে graph_traits<G>কেবলমাত্র Gনিজস্ব অভ্যন্তরীণ টাইপডেফগুলির জন্য ডিফল্ট প্রয়োগটি কোয়েরি ।
ডেনিস জিকিফুজ

1
এমনকি ০৩ টি স্ট্যান্ডার্ড লাইব্রেরি বৈশিষ্ট্যযুক্ত ক্লাসগুলি ব্যবহার করে যেখানে উপযুক্ত ... লাইব্রেরির দর্শনটি সাধারণভাবে ধারকগুলিতে চালনা করা নয়, তবে পুনরাবৃত্তকারীদের চালনা করা। সুতরাং এটি একটি iterator_traitsশ্রেণি সরবরাহ করে যাতে আপনার জেনেরিক অ্যালগরিদমগুলি সহজেই উপযুক্ত তথ্যের জন্য জিজ্ঞাসা করতে পারে। যা আবার তার নিজস্ব তথ্যের জন্য পুনরাবৃত্তিকারীকে জিজ্ঞাসা করতে ডিফল্ট। এর দীর্ঘ এবং সংক্ষিপ্তসারটি হ'ল বৈশিষ্টগুলি এবং অভ্যন্তরীণ টাইপডিফগুলি খুব কমই পারস্পরিক একচেটিয়া হয় ... তারা একে অপরকে সমর্থন করে।
ডেনিস জিকিফুজ

1
@ ডেনিস: iterator_traitsপ্রয়োজনীয় হয়ে উঠেছে কারণ এটির T*একটি মডেল হওয়া উচিত RandomAccessIteratorতবে আপনি প্রয়োজনীয় টাইপডেফগুলি এতে প্রবেশ করতে পারবেন না T*। একবার আমাদের হয়ে গেলে iterator_traits, নেস্টেড টাইপডেফগুলি অনর্থক হয়ে যায় এবং আমি আশা করি তারা সেখানে এবং পরে সরিয়ে ফেলা হয়েছে। একই কারণে (অভ্যন্তরীণ টাইপিডেফগুলি যুক্ত করতে অসম্ভবতা), T[N]এসটিএল Sequenceধারণাটি মডেল করে না এবং আপনার যেমন কুলেজ প্রয়োজন std::array<T,N>। বুস্ট.রেঞ্জ দেখায় যে আধুনিক সিকোয়েন্স ধারণাটি কীভাবে সংজ্ঞায়িত করা যায় যা T[N]মডেল করতে পারে , কারণ এটিতে নেস্টেড টাইপডিজ বা সদস্যের কার্যকারিতা প্রয়োজন হয় না।
মার্ক মুটজ - মিমুটজ


8

টাইপডিফগুলি অবশ্যই ভাল স্টাইল। এবং আপনার সমস্ত "কারণগুলি আমি পছন্দ করি" ভাল এবং সঠিক।

আপনার যে সমস্যা আছে সে সম্পর্কে। ঠিক আছে, ফরওয়ার্ড ডিক্লেয়ারেশন কোনও পবিত্র গ্রেইল নয়। বহু স্তরের নির্ভরতা এড়াতে আপনি কেবল আপনার কোডটি ডিজাইন করতে পারেন।

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

মাঝে মাঝে করতাম

Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map

এবং এটি সমস্ত ডোমেন শ্রেণীর জন্য এবং কিছু নির্দিষ্টকরণের জন্য কিছু বিশেষীকরণের সাথে ডিফল্ট হতে পারে।


3

এসটিএল সর্বদা এই ধরণের জিনিস করে - টাইপিডেফগুলি এসটিএলে অনেক শ্রেণির জন্য ইন্টারফেসের অংশ।

reference
iterator
size_type
value_type
etc...

সমস্ত টিডিডিফগুলি যা বিভিন্ন এসটিএল টেম্পলেট শ্রেণীর জন্য ইন্টারফেসের অংশ।


সত্য, এবং আমি সন্দেহ করি এটি এখানেই আমি প্রথমে তুলেছিলাম। দেখে মনে হচ্ছে এগুলি ন্যায়সঙ্গত করা একটু সহজ হবে? আপনি যদি 'মেটা-প্রোগ্রামিং' লাইন ধরে ভাবতে থাকেন তবে আমি ক্লাসের টেম্পলেটের মধ্যে টাইপডেফগুলি দেখতে আরও ভেরিয়েবলের অনুরূপ হিসাবে সহায়তা করতে পারি না।
বেকার উইল

3

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

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


3

বর্তমানে আমি কোড নিয়ে কাজ করছি, যা নিবিড়ভাবে এই ধরণের টাইপডেফগুলি ব্যবহার করে। এখনও পর্যন্ত এটি ঠিক আছে।

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

সুতরাং সেগুলি ব্যবহারের আগে কিছু বিষয় বিবেচনা করা উচিত

  • অন্য কারও কি এই টাইপিডসের প্রয়োজন? ক্লাসটি কি অন্যান্য ক্লাস দ্বারা প্রচুর ব্যবহৃত হয়?
  • আমি কি ব্যবহারটি ছোট করব বা ক্লাসটি আড়াল করব? (লুকানোর ক্ষেত্রে আপনি ইন্টারফেসের কথাও ভাবতে পারেন))
  • অন্যান্য লোকেরা কোড নিয়ে কাজ করছেন? তারা কিভাবে এটা করবেন? তারা কি এটিকে সহজ বলে মনে করবে বা তারা বিভ্রান্ত হবে?

1

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

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


এটি টাইপডেফদের সাথে নামবিহীন নাম স্থানটিকে কলুষিত করবে না ?! টাইপিডেফের সমস্যাটি হ'ল এটি প্রকৃত প্রকারটি গোপন করে, যা একাধিক মডিউলে অন্তর্ভুক্ত হওয়ার সাথে সংঘাত সৃষ্টি করতে পারে, যা খুঁজে পাওয়া / ঠিক করা শক্ত। এগুলিকে নেমস্পেসে বা ক্লাসের ভিতরে রাখা ভাল অনুশীলন।
Indy9000

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

ক্লাসের মধ্যে টাইপিডেফ লাগানোর জন্য আরেকটি যুক্তি হ'ল টেম্পলেটাইজড ফাংশনগুলির ব্যবহার। যখন, বলুন, কোনও ফাংশন অজানা স্ট্রিংয়ের ধরণ (স্ট্রিং বা আপনার নিজস্ব স্ট্রিং-কনফর্মেন্ট ভেরিয়েন্ট) ধারণ করে একটি অজানা ধারক প্রকার (ভেক্টর বা তালিকা) প্রাপ্ত করে। ধারক পেওলোডের ধরণটি নির্ধারণের একমাত্র উপায় টাইপডেফ 'মান_প্রকার' যা কনটেইনার শ্রেণির সংজ্ঞার অংশ।
মারিয়াস

1

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

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