সি ++ - কেন এখানে 'টেমপ্লেট' কীওয়ার্ডের প্রয়োজন?


9

আমার কাছে নিম্নলিখিত কোড রয়েছে:

template <typename TC>
class C
{
    struct S
    {
        template <typename TS>
        void fun() const
        {}
    };

    void f(const S& s)
    {
        s.fun<int>();
    }
};

// Dummy main function
int main()
{
    return 0;
}

এটি জিসিসি 9.2 এবং ক্ল্যাং (9.0) উভয় দিয়ে তৈরি করার সময়, templateকীওয়ার্ডটি চাওয়ার জন্য প্রয়োজনীয় হওয়ার কারণে আমি একটি সংকলন ত্রুটি পেয়ে যাচ্ছি fun। ঝাঁকুনি শো:

error: use 'template' keyword to treat 'fun' as a dependent template name
        s.fun<int>();
          ^
          template 

কম্পাইলার কেন funপ্রসঙ্গে একটি নির্ভরশীল নাম বলে আমি বুঝতে পারি না f, যেহেতু fএটি কোনও টেম্পলেট নয়। আমি যদি Cকোনও টেমপ্লেটের পরিবর্তে নিয়মিত ক্লাসে পরিবর্তন করি তবে ত্রুটিটি চলে যায়; তবে আমি দেখতে পাচ্ছি না কেন যেহেতু প্রথম স্থানে একটি ত্রুটি হতে তন্ন তন্ন উচিত Sকিংবা fউপর নির্ভর করে TC

অদ্ভুতভাবে যথেষ্ট, এমএসভিসি 19.22 এটি ঠিক জরিমানা করে।


বিঃদ্রঃ

ভোটিং আগে এর প্রতারিত যেমন বন্ধ করতে কোথায় এবং কেন আমি "টেমপ্লেট" এবং "typename" কিওয়ার্ড করা হবে? দয়া করে এটি একটি বিশেষ ক্ষেত্রে বিবেচনা করুন যেখানে Sপ্রকৃতপক্ষে নির্ভরশীল নাম হলেও fএটি প্রাসঙ্গিকভাবে নির্ভর করে না যদি না তারা বর্তমান ইনস্ট্যানটিশনের সদস্য হয়।


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
Bhargav রাও

উত্তর:


10

বিবেচনা করুন :

template<typename T>
struct C
{
    struct S
    {
        int a = 99;
    };

    void f(S s, int i)
    {
        s.a<0>(i);
    }
};

template<>
struct C<long>::S
{
    template<int>
    void a(int)
    {}
};

int main()
{
    C<int>{}.f({}, 0); // #1
    C<long>{}.f({}, 0); // #2
}

s.a<0>(i)দুই তুলনা অপারেশনের সম্পর্কে একটি অভিব্যক্তি হিসাবে পার্স করা হয় <এবং >, এবং এই # 1 জন্য ভালো কিন্তু # 2 জন্য ব্যর্থ।

যদি এটিতে পরিবর্তিত হয় s.template a<0>(i)তবে # 2 ঠিক আছে এবং # 1 ব্যর্থ হয়। সুতরাং templateকীওয়ার্ডটি এখানে কখনও অপ্রয়োজনীয় নয়।

এমএসভিসি একই প্রোগ্রামের মধ্যে উভয় উপায়েই এক্সপ্রেশনটি ব্যাখ্যা করতে সক্ষমs.a<0>(i) । তবে এটি স্ট্যান্ডার্ড অনুযায়ী সঠিক নয়; কম্পাইলারের সাথে ডিল করার জন্য প্রতিটি এক্সপ্রেশনের কেবল একটি পার্স থাকা উচিত।


আমি এখনও এটি পুরোপুরি বুঝতে পারি না। আপনার উদাহরণ থেকে বোঝা যায় যে Cএক্ষেত্রে আপনি হয় অন্য কোনও বিশেষায়িত ব্যবহার করেন তবে আপনি উভয়কেই তাত্পর্যপূর্ণ করতে পারবেন না। এখানে templateকীওয়ার্ডটি এখনও অপ্রয়োজনীয় আইএমএইচও, কারণ কোনটি Sবাছাই হয়ে যায় তার উপর নির্ভর করে Cআপনি কোনটি ইনস্ট্যান্ট করবেন। templateকীওয়ার্ড ব্যতীত আপনি উভয়ই ইনস্ট্যান্ট করতে সক্ষম হবেন এবং প্রতিটি উদাহরণের জন্য চ এর আচরণ পৃথক হতে পারে।
মার্টিন

2
@ মার্টিন কথাটি হ'ল প্রতিটি টোকেনের উত্স ফাইলে কেবল একটি সিনট্যাকটিক ভূমিকা থাকতে হবে। উদাহরণস্বরূপ, টোকেনের <জন্য একটি টেম্পলেট ইনস্ট্যান্টিয়েশনে তুলনামূলক অপারেটর এবং অন্য ইনস্ট্যান্টেশনে একটি উদ্বোধনী কোণ বন্ধনী হওয়া ঠিক হবে না। এটি নিশ্চিত করার জন্য যে সংকলকরা একটি এএসটিতে টেম্পলেটগুলি পার্স করতে পারে (টেমপ্লেটের ধরণের স্থানধারক সহ)।
ইকামত্মুর

এটা বোধগম্য. ধন্যবাদ!
মার্টিন

7

funএর টেম্পলেট প্যারামিটারের উপর নির্ভর করে কোনও টেম্পলেট ফাংশন (বা একেবারেই নাও থাকতে পারে) হতে পারে class C

এটি কারণ আপনি বিশেষজ্ঞ করতে পারেন S(বিশেষায়িত না করে C):

template <> struct C<int>::S {};

কারণ সংকলকটি জানতে চায় যে funকোনও টেম্পলেট কিনা এবং প্রথমে দেখার সময় class C(টেমপ্লেটের প্যারামিটারটি প্রতিস্থাপনের আগে) templateপ্রয়োজনীয়।


1
মন ...
ফুঁকছে

তারপরে, এর অনুসরণ অনুসারে, এই নতুন সংজ্ঞাগুলির Sদ্বারা কখনও অ্যাক্সেস করা যায় কিনা f। যদি তারা না পারে তবে এই বিধিনিষেধটি থাকা অর্থপূর্ণ নয় কারণ fতারা সেগুলি আর দেখতে পাবে না।
মার্টিন

@ মার্টিন জিসিসি, কলং এবং এমএসভিসি উভয়ের সাথে fএটি খুঁজে পেয়েছে ।
হলিব্ল্যাকগেট

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