গতিশীল পলিমারফিজম এড়াতে সিআরটিপি


উত্তর:


143

দুটি উপায় আছে।

প্রথমটি হ'ল ধরণের কাঠামোর জন্য ইন্টারফেসটি স্থিরভাবে উল্লেখ করে:

template <class Derived>
struct base {
  void foo() {
    static_cast<Derived *>(this)->foo();
  };
};

struct my_type : base<my_type> {
  void foo(); // required to compile.
};

struct your_type : base<your_type> {
  void foo(); // required to compile.
};

দ্বিতীয়টি হ'ল রেফারেন্স-টু-বেস বা পয়েন্টার-টু-বেস আইডিয়মের ব্যবহার এড়ানো এবং সংকলনের সময় তারগুলি করা। উপরের সংজ্ঞাটি ব্যবহার করে, আপনি টেমপ্লেট ফাংশনগুলি দেখতে পারেন যা দেখতে এর মতো দেখায়:

template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
  obj.foo(); // will do static dispatch
}

struct not_derived_from_base { }; // notice, not derived from base

// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload

সুতরাং কাঠামো / ইন্টারফেস সংজ্ঞা এবং আপনার ফাংশনগুলিতে সংকলন-টাইপ টাইপ ছাড়ের সংমিশ্রণ আপনাকে গতিশীল প্রেরণের পরিবর্তে স্থিতিশীল প্রেরণ করার অনুমতি দেয়। এটি স্ট্যাটিক পলিমারফিজমের সারাংশ।


4
আমি যে জোর চাই not_derived_from_baseথেকে প্রাপ্ত করা হয় না base, না এটা থেকে উদ্ভূত হয় base...
leftaroundabout

4
আসলে, আমার_প্রকার / আপনার_প্রকারের ভিতরে ফু () এর ঘোষণার প্রয়োজন নেই। codepad.org/ylpEm1up (স্ট্যাক ওভারফ্লো কারণ) - সংকলনের সময় foo এর সংজ্ঞা কার্যকর করার কোনও উপায় আছে কি? - ঠিক আছে, একটি সমাধান খুঁজে পেয়েছেন: ideone.com/C6Oz9 - সম্ভবত আপনি নিজের উত্তরে এটি সংশোধন করতে চান।
কুকি 451

4
আপনি কি আমাকে ব্যাখ্যা করতে পারবেন এই উদাহরণে সিআরটিপি ব্যবহার করার প্রেরণা কী? যদি বারটি টেমপ্লেট হিসাবে চিহ্নিত করা হয় <ক্লাস টি> শূন্য বার (টি ও আপত্তি) {obj.foo (); এবং, তারপরে foo সরবরাহ করে এমন কোনও শ্রেণি ঠিক থাকবে। সুতরাং আপনার উদাহরণের ভিত্তিতে দেখে মনে হচ্ছে সিআরটিপি-র একমাত্র ব্যবহারটি সংকলন সময়ে ইন্টারফেসটি নির্দিষ্ট করা। এটা কি এর জন্য?
আন্তন ডানিয়েকো

4
@ ডিন মাইকেল প্রকৃতপক্ষে উদাহরণের কোডটি সংকলন করেও যদি foo আমার_প্রকার এবং আপনার_ টাইপে সংজ্ঞায়িত না হয়। এই ভিত্তিকে ওভাররাইড ছাড়াই :: fooকে পুনরাবৃত্তভাবে বলা হয় (এবং স্ট্যাকওভারফ্লো)। সুতরাং সম্ভবত আপনি উত্তরটি সংশোধন করতে চান যেমন কুকি 451 দেখিয়েছে?
আন্তন ডানিয়েকো

@ মেজাকা: হ্যাঁ, ডিন মাইকেলের উদাহরণটি অসম্পূর্ণ কারণ এটি আপনি যেমন দেখান ঠিক ততটাই সিআরটিপি ছাড়াই আরও সংক্ষিপ্তভাবে প্রয়োগ করা যেতে পারে। তবে একটি যুক্ত করুন template<class T> bar(base2<T> &obj) { obj.quux(); }- একটি আলাদা bar()বাস্তবায়ন সহ দ্বিতীয় স্তরের শ্রেণি - এবং সিআরটিপি-র উপযোগিতা স্পষ্ট হয়ে ওঠে।
নিমো

18

আমি নিজে সিআরটিপি সম্পর্কে শালীন আলোচনা খুঁজছি। বৈজ্ঞানিক সি ++ এর জন্য টড ভেলদুইজেনের কৌশলগুলি এটি (1.3) এবং এক্সপ্রেশন টেম্পলেটগুলির মতো আরও অনেক উন্নত কৌশল resource

এছাড়াও, আমি দেখতে পেয়েছি যে আপনি কোপলিনের বেশিরভাগ মূল সি ++ রত্ন নিবন্ধ গুগল বইতে পড়তে পারেন। হয়তো এখনও সেই ঘটনা।


@ ফিজার আপনার প্রস্তাবিত অংশটি আমি পড়েছি, তবে এখনও বুঝতে পারছি না <ট ক্লাস টি_ফেলাফটি> ডাবল যোগ (ম্যাট্রিক্স <T_leaftype> এবং এ) টেম্পলেটটি কী করে; টেমপ্লেট <ক্লাস যাই হোক না কেন> ডাবল যোগের (যাই হোক না কেন & এ) এর তুলনায় আপনাকে কিনে;
আন্তন ড্যানিয়েকো

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

1

আমাকে সিআরটিপি দেখতে হবে । এটি করার পরেও আমি স্ট্যাটিক পলিমারফিজম সম্পর্কে কিছু জিনিস পেয়েছি । আমি সন্দেহ করি যে এটিই আপনার প্রশ্নের উত্তর।

দেখা যাচ্ছে যে এটিএল এই প্যাটার্নটি বেশ ব্যাপকভাবে ব্যবহার করে।


-5

এই উইকিপিডিয়া উত্তরে আপনার যা যা প্রয়োজন তা রয়েছে। যথা:

template <class Derived> struct Base
{
    void interface()
    {
        // ...
        static_cast<Derived*>(this)->implementation();
        // ...
    }

    static void static_func()
    {
        // ...
        Derived::static_sub_func();
        // ...
    }
};

struct Derived : Base<Derived>
{
    void implementation();
    static void static_sub_func();
};

যদিও আমি জানি না এটি আসলে আপনাকে কতটা কিনে। ভার্চুয়াল ফাংশন কলের ওভারহেড হ'ল (অবশ্যই সংকলক নির্ভরশীল):

  • স্মৃতি: ভার্চুয়াল ফাংশন প্রতি এক ফাংশন পয়েন্টার
  • রানটাইম: একটি ফাংশন পয়েন্টার কল

সিআরটিপি স্থির পলিমারফিজমের ওভারহেডটি যখন:

  • মেমোরি: টেমপ্লেট ইনস্ট্যান্টেশন প্রতি বেসের সদৃশ
  • রানটাইম: একটি ফাংশন পয়েন্টার কল + যা কিছু স্ট্যাটিক_কাস্ট করছে

4
প্রকৃতপক্ষে, প্রতি টেমপ্লেট ইনস্ট্যান্টাইজেশন বেসের সদৃশ একটি বিভ্রম কারণ (আপনার যদি এখনও কোনও ভিটিবেল না থাকে) সংকলকটি আপনার জন্য একক কাঠামোতে বেসের সঞ্চয়স্থান এবং প্রাপ্ত উত্সকে একত্রিত করবে। ফাংশন পয়েন্টার কলটিও সংকলক (স্ট্যাটিক_কাস্ট অংশ) দ্বারা অপ্টিমাইজ করা হয়েছে।
ডিন মাইকেল 18

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

4
আমার বক্তব্যটি হ'ল বেস কোডটি সমস্ত টেম্পলেট দৃষ্টান্তে নকল করা হবে (আপনি যে মার্জিংয়ের কথা বলছেন)। একমাত্র টেমপ্লেট প্যারামিটারের উপর নির্ভর করে এমন একটি পদ্ধতি সহ একটি টেম্পলেট রয়েছে; বেস ক্লাসে অন্য সমস্ত কিছু ভাল হয় অন্যথায় এটি একাধিকবার টানা হয় ('মার্জড')।
ব্যবহারকারী 23167

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

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