একটি সি ++ টেম্পলেট শ্রেণি কীভাবে ঘোষণা করবেন?


105

নিম্নলিখিতগুলির মতো একটি টেম্পলেট শ্রেণি দেওয়া হয়েছে:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

হেডার ফাইলে কেউ এই ক্লাসটি কীভাবে ঘোষণা করতে পারে?

উত্তর:


108

আপনি এটি এইভাবে করবেন:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings;

template<typename Type, typename IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

মনে রাখবেন যে ডিফল্টটি ফরোয়ার্ড ঘোষণায় থাকে এবং আসল সংজ্ঞাতে নয়।


এমন কোনও শ্রেণীর ফরোয়ার্ড-ডিক্লেয়ার করা সম্ভব যেখানে এর সংজ্ঞাটিতে তার ডিফল্ট তালিকাভুক্ত থাকে। আমার উত্তর দেখুন।
এলিয়ট

আমি একমত নই স্ট্যান্ডার্ডটি বলে: "একটি টেমপ্লেট-প্যারামিটারকে একই সুযোগে দুটি পৃথক ঘোষণার মাধ্যমে ডিফল্ট যুক্তি দেওয়া হবে না" । এবং আমি প্রথম ঘোষণার মধ্যে খেলাপি সম্পর্কে কিছুই পাই নি। এছাড়াও সংজ্ঞায়নের ফরওয়ার্ড ডিক্লেয়ারেশন এবং ডিফল্ট সহ কোডটি সাফল্যের সাথে সংকলন ও রান করে। আপনি কী দাবি করছেন তা সম্পর্কে আপনি কি নিশ্চিত? আপনি স্ট্যান্ডার্ড থেকে একটি উদ্ধৃতি প্রদান করতে পারেন?
oleksijp

@ এলিয়ট মনে হচ্ছে এটি সত্য। স্ট্যান্ডার্ড [17.1.9] বলেছেন: " একটি টেম্পলেট ঘোষণায় একটি ডিফল্ট টেম্পলেট-যুক্তি নির্দিষ্ট করা যেতে পারে " " অবশ্যই হবে না, তবে হতে পারে। সুতরাং অন্য উত্তরগুলি কেন এটি প্রথম ঘোষণায় হওয়া উচিত তা আমি বুঝতে পারি না।
oleksijp

এবং সংজ্ঞাটিতে খেলাপি থাকা অনেক বেশি সুবিধাজনক বলে মনে হয়।
oleksijp

8

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


এমন কোনও শ্রেণীর ফরোয়ার্ড-ডিক্লেয়ার করা সম্ভব যেখানে এর সংজ্ঞাটিতে তার ডিফল্ট তালিকাভুক্ত থাকে। আমার উত্তর দেখুন।
এলিয়ট

আমি একমত নই স্ট্যান্ডার্ডটি বলে: "একটি টেমপ্লেট-প্যারামিটারকে একই সুযোগে দুটি পৃথক ঘোষণার মাধ্যমে ডিফল্ট যুক্তি দেওয়া হবে না" । এবং আমি প্রথম ঘোষণার মধ্যে খেলাপি সম্পর্কে কিছুই পাই নি। এছাড়াও সংজ্ঞায়নের ফরওয়ার্ড ডিক্লেয়ারেশন এবং ডিফল্ট সহ কোডটি সাফল্যের সাথে সংকলন ও রান করে। আপনি কী দাবি করছেন তা সম্পর্কে আপনি কি নিশ্চিত? আপনি স্ট্যান্ডার্ড থেকে একটি উদ্ধৃতি প্রদান করতে পারেন?
oleksijp

4

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

যেমন আসুন std::vectorএটি বাদ দিয়ে ব্যবহার করা যাক (এর দ্বিতীয় তর্কটি std::vectorএকটি ডিফল্ট দিয়ে সংজ্ঞায়িত করা হয়):

namespace std
{
    template<typename, typename>
    class vector;
}

#include <iostream>

template <typename S, typename T>
void Foo (const std::vector<S,T> & vector)
{
    std::cout << "do vector stuff, eg., display size = "
        << vector.size() << std::endl;
}

template <typename T>
void Foo (const T & t)
{
    std::cout << "do non-vector stuff..." << std::endl;
}

তারপরে আমরা ভেক্টরকে অন্তর্ভুক্ত না করে এটি ব্যবহার করতে পারি :

int main ()
{
    Foo(3);
}

... অথবা আমরা এটি ব্যবহার করতে পারেন সঙ্গে std::vector , যেমন .:

#include <vector>

// Now the compiler understands how to handle
// std::vector with one argument
// (making use of its default argument)

int main ()
{
    Foo(std::vector<int>(3));
}

আমি মানগুলি পরীক্ষা করে দেখিনি, তবে এটি কাজ করে clang/ gccচালিয়ে -std=c++98যায় -std=c++17, সুতরাং এটি যদি আনুষ্ঠানিকভাবে কোনও মান না হয় তবে এটি আনুষ্ঠানিকভাবে বলে মনে হচ্ছে।


হতে পারে আপনি খালি অ্যাঙ্গেল বন্ধনীগুলি ভুলে গেছেন Foo<> foo;
oleksijp
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.