বড় টেম্পলেটগুলির প্রয়োগের জন্য সি ++ পছন্দসই পদ্ধতি


10

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

অনলাইনে দেখার সময় টেমপ্লেট ক্লাস পরিচালনা করার সর্বোত্তম উপায় সম্পর্কে 2 মতামত রয়েছে বলে মনে হয়:

1. শিরোনামে সম্পূর্ণ ঘোষণা এবং বাস্তবায়ন।

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

২. শেষের মধ্যে অন্তর্ভুক্ত করা ফাইল (.tpp) অন্তর্ভুক্ত কোনও টেম্পলেটে প্রয়োগটি লিখুন।

এটি আমার কাছে আরও ভাল সমাধানের মতো বলে মনে হচ্ছে তবে এটি ব্যাপকভাবে প্রয়োগ করা হবে বলে মনে হয় না। এই পদ্ধতির নিকৃষ্টতর হওয়ার কোনও কারণ আছে কি?

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


1
কোডেপ্রজেক্ট.কম এ 9 বছরের পুরানো নিবন্ধটি দেখুন । পদ্ধতি 3 আপনি বর্ণিত কি। আপনি যেমন বিশ্বাস করেন তেমন বিশেষ বলে মনে হয় না।
ডক ব্রাউন

.. বা এখানে, একই পদ্ধতি, 2014 থেকে নিবন্ধ: কোড ofhonour.blogspot.com/2014/11/…
ডক ব্রাউন

2
নিবিড়ভাবে সম্পর্কিত: stackoverflow.com/q/1208028/179910 । Gnu সাধারণত ".tpp" এর পরিবর্তে ".tcc" এক্সটেনশন ব্যবহার করে তবে এটি অন্যথায় বেশ অভিন্ন।
জেরি কফিন

আমি সবসময় এক্সটেনশন হিসাবে "আইপিপি" ব্যবহার করি, তবে আমি যে কোড লিখেছি তাতে একই জিনিসটি অনেকটা করেছি।
সেবাস্তিয়ান রেডল

উত্তর:


6

টেম্প্লেটেড সি ++ ক্লাস লেখার সময় আপনার কাছে সাধারণত তিনটি বিকল্প থাকে:

(1) শিরোনামে ঘোষণা এবং সংজ্ঞা রাখুন।

// foo.h
#pragma once

template <typename T>
struct Foo
{
    void f()
    {
        ...
    }
};

অথবা

// foo.h
#pragma once

template <typename T>
struct Foo
{
    void f();
};

template <typename T>
inline void Foo::f()
{
    ...
}

প্রো:

  • খুব সুবিধাজনক ব্যবহার (কেবল শিরোনাম অন্তর্ভুক্ত)।

কন:

  • ইন্টারফেস এবং পদ্ধতি বাস্তবায়ন মিশ্রিত হয়। এটি "কেবল" একটি পঠনযোগ্যতা সমস্যা problem কিছু এটি অনিবার্য মনে করে, কারণ এটি স্বাভাবিক .h / .cpp পদ্ধতির চেয়ে পৃথক। তবে, সচেতন হন যে অন্যান্য ভাষায় এটি কোনও সমস্যা নয়, উদাহরণস্বরূপ, সি # এবং জাভা।
  • উচ্চ পুনর্নির্মাণের প্রভাব: আপনি Fooসদস্য হিসাবে নতুন ক্লাস ঘোষণা করলে আপনাকে অন্তর্ভুক্ত করা দরকার foo.h। এর অর্থ Foo::fহ্যাডার এবং উত্স ফাইল উভয়ের মাধ্যমে প্রচারগুলির বাস্তবায়ন পরিবর্তন করা।

পুনর্নির্মাণের প্রভাবটি ঘনিষ্ঠভাবে দেখে নেওয়া যাক: অ-পরীক্ষিত সি ++ ক্লাসের জন্য আপনি। এই পদ্ধতিতে, যখন কোনও পদ্ধতির বাস্তবায়ন পরিবর্তন করা হয়, কেবলমাত্র একটি .cpp পুনরায় সংযোগ করা প্রয়োজন। এটি। টেম্পলেট ক্লাসগুলির জন্য আলাদা হয় যদি .h এ আপনার সমস্ত কোড থাকে। নিম্নলিখিত উদাহরণটি একবার দেখুন:

// bar.h
#pragma once
#include "foo.h"
struct Bar
{
    void b();
    Foo<int> foo;
};

// bar.cpp
#include "bar.h"
void Bar::b()
{
    foo.f();
}

// qux.h
#pragma once
#include "bar.h"
struct Qux
{
    void q();
    Bar bar;
}

// qux.cpp
#include "qux.h"
void Qux::q()
{
    bar.b();
}

এখানে, শুধুমাত্র Foo::fভিতরে ব্যবহার করা হয় bar.cpp। তবে, আপনি যদি Foo::fউভয়টির বাস্তবায়ন পরিবর্তন করেন bar.cppএবং উভয়ই qux.cppপুনরায় সংযুক্ত করা দরকার। Foo::fউভয় ফাইলে জীবন বাস্তবায়ন , যদিও কোনও অংশই Quxসরাসরি কিছু ব্যবহার করে না Foo::f। বড় প্রকল্পগুলির জন্য, এটি শীঘ্রই একটি সমস্যায় পরিণত হতে পারে।

(২) .hpp এবং সংজ্ঞা .tpp এ রাখুন এবং এটি .h এর মধ্যে অন্তর্ভুক্ত করুন।

// foo.h
#pragma once
template <typename T>
struct Foo
{
    void f();
};
#include "foo.tpp"    

// foo.tpp
#pragma once // not necessary if foo.h is the only one that includes this file
template <typename T>
inline void Foo::f()
{
    ...
}

প্রো:

  • খুব সুবিধাজনক ব্যবহার (কেবল শিরোনাম অন্তর্ভুক্ত)।
  • ইন্টারফেস এবং পদ্ধতির সংজ্ঞা পৃথক করা হয়।

কন:

  • উচ্চ পুনর্নির্মাণ প্রভাব (একই (1) )।

এই সমাধানটি .h / .cpp এর মতো দুটি পৃথক ফাইলে ঘোষণা এবং পদ্ধতির সংজ্ঞা পৃথক করে। যাইহোক, এই পদ্ধতির (1) হিসাবে একই পুনর্নির্মাণ সমস্যা রয়েছে, কারণ শিরোনামটিতে সরাসরি পদ্ধতির সংজ্ঞা রয়েছে।

(3) .hpp এবং সংজ্ঞা .tpp মধ্যে রাখুন, কিন্তু .tpp মধ্যে অন্তর্ভুক্ত .h।

// foo.h
#pragma once
template <typename T>
struct Foo
{
    void f();
};

// foo.tpp
#pragma once
template <typename T>
void Foo::f()
{
    ...
}

প্রো:

  • .H / .cpp বিভাজনের মতো পুনর্নির্মাণের প্রভাব হ্রাস করে।
  • ইন্টারফেস এবং পদ্ধতির সংজ্ঞা পৃথক করা হয়।

কন:

  • অসুবিধাজনক ব্যবহার: Fooকোনও ক্লাসে সদস্য যুক্ত করার সময় Barআপনাকে foo.hহেডারে অন্তর্ভুক্ত করতে হবে । আপনাকে কল যদি Foo::fএকটি .cpp, আপনি এছাড়াও অন্তর্ভুক্ত করা আছে foo.tppসেখানে।

এই পদ্ধতিটি পুনর্নির্মাণের প্রভাবকে হ্রাস করে, যেহেতু কেবলমাত্র .cpp ফাইলগুলি যা সত্যই ব্যবহার করে Foo::fতা পুনরায় সংযুক্ত করা দরকার। তবে, এটি একটি মূল্যে আসে: এই সমস্ত ফাইলগুলিকে অন্তর্ভুক্ত করা দরকার foo.tpp। উপর থেকে উদাহরণটি গ্রহণ করুন এবং নতুন পদ্ধতির ব্যবহার করুন:

// bar.h
#pragma once
#include "foo.h"
struct Bar
{
    void b();
    Foo<int> foo;
};

// bar.cpp
#include "bar.h"
#include "foo.tpp"
void Bar::b()
{
    foo.f();
}

// qux.h
#pragma once
#include "bar.h"
struct Qux
{
    void q();
    Bar bar;
}

// qux.cpp
#include "qux.h"
void Qux::q()
{
    bar.b();
}

যেহেতু আপনি দেখতে পারেন, শুধু পার্থক্য অতিরিক্ত এর অন্তর্ভুক্ত হয় foo.tppbar.cpp। এটি অসুবিধাগুলি এবং ক্লাসের জন্য একটি সেকেন্ড যুক্ত করার উপর নির্ভর করে আপনি এটির পদ্ধতিগুলি কল করেন কিনা তা নির্ভর করে। তবে, আপনি পুনর্নির্মাণের প্রভাব হ্রাস করুন: bar.cppআপনি যদি এর বাস্তবায়ন পরিবর্তন করেন তবে কেবল পুনরায় সংযুক্ত করা দরকার Foo::f। ফাইলটির qux.cppকোনও পুনঃসংশোধনের প্রয়োজন নেই।

সারসংক্ষেপ:

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

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


2

অনুরূপ .tppধারণা (যা আমি দেখেছি কখনও ব্যবহার করেছেন), আমরা একটি মধ্যে সবচেয়ে ইনলাইন কার্যকারিতা করা -inl.hppযা স্বাভাবিকের শেষে অন্তর্ভুক্ত করা হয় ফাইল .hppফাইল।

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


1

২ য় বৈকল্পিকের একটি প্রো মুদ্রা হ'ল আপনার শিরোনামগুলি আরও পরিপাটি দেখাচ্ছে।

কন হতে পারে আপনার ইনলাইন আইডিই ত্রুটি পরীক্ষা করতে পারে, এবং ডিবাগার বাইন্ডিংগুলি খারাপ হতে পারে।


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

0

আমি প্রয়োগটি পৃথক পৃথক ফাইলে রাখার পদ্ধতিকে খুব পছন্দ করি এবং শিরোনাম ফাইলটিতে কেবলমাত্র ডকুমেন্টেশন এবং ডিকোলেশন রয়েছে।

সম্ভবত আপনি ব্যবহারের ক্ষেত্রে এই পদ্ধতির বেশি ব্যবহার না হওয়ার কারণ, আপনি কি সঠিক জায়গাগুলি সন্ধান করেন নি ;-)

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

উদাহরণস্বরূপ এই লাইব্রেরিটি নিন: https://github.com/SophistSolutions/Stroika/

পুরো গ্রন্থাগারটি এই পদ্ধতির সাথে লেখা এবং আপনি যদি কোডটি দেখেন তবে আপনি দেখতে পাবেন যে এটি কতটা ভাল কাজ করে।

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

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

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