বিভ্রান্তিকর টেম্পলেট ত্রুটি


91

আমি কিছুক্ষণ ঝাঁকুনির সাথে খেলছি, এবং আমি "টেস্ট / সেমেটেম্পলেট / ডিপেন্ডেন্ট-টেম্পলেট-রিকর্ডার। সিপি" (ঝনঝন ডিস্ট্রিবিউশনে), যা কোনও টেমপ্লেট ত্রুটি থেকে পুনরুদ্ধার করার জন্য ইঙ্গিত সরবরাহ করার কথা বলে মনে করে হোঁচট খেয়েছি।

পুরো জিনিসটি খুব সহজেই একটি সর্বনিম্ন উদাহরণে নামিয়ে দেওয়া যায়:

template<typename T, typename U, int N> struct X {
    void f(T* t)
    {
        // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
        t->f0<U>();
    }
};

ঝাঁকুনির দ্বারা প্রাপ্ত ত্রুটি বার্তা:

tpl.cpp:6:13: error: use 'template' keyword to treat 'f0' as a dependent template name
         t->f0<U>();
            ^
            template 
1 error generated.

... তবে আমার বুঝতে templateখুব অসুবিধা হয়েছে যে কোডটি সিনট্যাকটিক্যালি সঠিক হওয়ার জন্য কীওয়ার্ডটি সন্নিবেশ করানোর কথা ছিল ?


11
তীরটি যেখানে নির্দেশ করছে সেখানে আপনি এটি সন্নিবেশ করানোর চেষ্টা করেছিলেন?
মাইক সিমুর

4
অনুরূপ এই এবং এই
প্রসুন সৌরভ

উত্তর:


104

আইএসও সি ++ 03 14.2 / 4:

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

ইন t->f0<U>(); f0<U>একটি সদস্য টেমপ্লেট বিশেষীকরণ হয় যা পরে প্রদর্শিত হয় ->এবং যা স্পষ্টভাবে টেম্পলেট প্যারামিটারের উপর নির্ভর করে Uতাই সদস্য টেমপ্লেট বিশেষায়িতকরণ অবশ্যই মূলশব্দ দ্বারা উপসর্গ করা উচিত template

তাই পরিবর্তন t->f0<U>()করার জন্য t->template f0<U>()


মজার বিষয় হল, আমি ভাবলাম বন্ধুত্বের মধ্যে অভিব্যক্তিটি স্থাপন করা: t->(f0<U>())এটি যেমন স্থির করে দিতেন, যেমনটি আমি f0<U>()স্বতন্ত্র প্রকাশের পক্ষে রাখি ... ভাল, আমি ভুল ভেবেছিলাম, মনে হচ্ছে ...

24
আপনি সম্ভবত মন্তব্য করতে পারেন কেন এই ঘটনা? সি ++ এর জন্য এই ধরণের সিনট্যাক্সের প্রয়োজন হবে কেন?
কৌতুহল

4
হ্যাঁ এটা অদ্ভুত। ভাষাটি "সনাক্ত" করতে পারে যে টেম্পলেট কীওয়ার্ডটি উপস্থিত থাকা দরকার। যদি এটি এটি করতে পারে তবে এটির মধ্যে কীওয়ার্ডটি কেবল "সন্নিবেশ" করা উচিত।
এনরিকো বোরবা

26

অন্যরা তৈরি করা পয়েন্টগুলি ছাড়াও খেয়াল করুন যে মাঝে মাঝে সংকলক তার মন তৈরি করতে পারে না এবং তাত্ক্ষণিকভাবে উভয় ব্যাখ্যা বিকল্প বৈধ প্রোগ্রাম পেতে পারে

#include <iostream>

template<typename T>
struct A {
  typedef int R();

  template<typename U>
  static U *f(int) { 
    return 0; 
  }

  static int f() { 
    return 0;
  }
};

template<typename T>
bool g() {
  A<T> a;
  return !(typename A<T>::R*)a.f<int()>(0);
}


int main() {
  std::cout << g<void>() << std::endl;
}

এই কপি করে প্রিন্ট 0যখন বাদ templateসামনে f<int()>কিন্তু 1যখন এটি ঢোকাতে। কোডটি কী করে তা নির্ধারণ করার জন্য আমি এটি অনুশীলন হিসাবে রেখেছি।


4
এখন এটি একটি পৈশাচিক উদাহরণ!
ম্যাথিউ এম।

4
ভিজ্যুয়াল স্টুডিও ২০১৩ এ আপনি যে আচরণটি বর্ণনা করছেন তা আমি পুনরুত্পাদন করতে পারি না It এটি সর্বদা কল করে f<U>এবং সর্বদা প্রিন্ট করে 1, যা আমার কাছে সঠিক ধারণা দেয়। templateকীওয়ার্ডটির প্রয়োজনীয়তা এবং এতে কী পার্থক্য হয় তা আমি এখনও বুঝতে পারি না ।
ভায়োলেট জিরাফ

@ ভায়োলেট ভিএসসি ++ সংকলক কোনও কমপ্লায়েন্ট সি ++ সংকলক নয়। একটি নতুন প্রশ্ন দরকার যদি আপনি জানতে চান কেন ভিএসসি ++ সর্বদা প্রিন্ট করে
needed

4
এই উত্তরটি কেন templateপ্রয়োজন তা ব্যাখ্যা করে : স্ট্যাকওভারফ্লো.com/ প্রশ্নগুলি / 10১০২45৫/… কেবলমাত্র স্ট্যান্ডার্ডিজ শর্তাদির উপর নির্ভর না করে যা বোঝা শক্ত। উত্তরটিতে কিছু এখনও বিভ্রান্ত হলে দয়া করে রিপোর্ট করুন।
জোহানেস স্কাউব -

@ জোহানেস শ্যাব-লিটব: ধন্যবাদ, দুর্দান্ত উত্তর। দেখা যাচ্ছে, আমি এটি আগে পড়েছি কারণ এটি ইতিমধ্যে আমার দ্বারা আপলোড করা হয়েছিল। স্পষ্টতই, আমার স্মৃতি মেহ।
ভায়োলেট জিরাফ 24'14

12

ক্যারেট যেখানে রয়েছে তার ঠিক আগে এটি প্রবেশ করান:

template<typename T, typename U, int N> struct X {
     void f(T* t)
     {
        t->template f0<U>();
     }
};

সম্পাদনা: আপনি যদি কোনও সংকলকের মতো মনে করেন তবে এই নিয়মের কারণ আরও স্পষ্ট হয়ে ওঠে। সংকলকরা সাধারণত একবারে এক বা দুটি টোকেনের দিকে তাকাতে থাকে এবং বাকী বাকরূপে সাধারণত "প্রত্যাশিত" হয় না। [সম্পাদনা: মন্তব্য দেখুন] কীওয়ার্ডের কারণটি একই রকম কারণ typenameনির্ভরশীল প্রকারের নামগুলি নির্দেশ করতে আপনার কীওয়ার্ডের প্রয়োজন কেন : এটি সংকলককে বলছে "আরে, আপনি যে শনাক্তকারীটি দেখতে পাচ্ছেন তা একটি টেম্পলেটটির নাম নয় বরং স্থিতিশীল ডেটা সদস্যের নাম এবং তারপরে স্বল্প-চিহ্নের চেয়ে কম "।


4
আমি কখনই এটি অনুমান করতে পারতাম না ... তবে আপনাকে ধন্যবাদ ;-)। সি ++ সম্পর্কে জানার জন্য এখানে সবসময়ই স্পষ্টতই কিছু থাকে!

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

@ জোহানেস স্কাউব - লিটব: ঠিক আছে, তাই সামনের অভিব্যক্তির চেয়ে অভিব্যক্তির সাথে সামঞ্জস্যপূর্ণ অর্থপূর্ণ অর্থ নির্ধারণ করা আরও বেশি সমস্যা।
ডগ

11

থেকে উদ্ধৃতাংশ সি ++ টেমপ্লেট

.Template কনস্ট্রাক্ট টাইপনেম প্রবর্তনের পরে একটি খুব অনুরূপ সমস্যাটি আবিষ্কার হয়েছিল। স্ট্যান্ডার্ড বিটসেট প্রকারটি ব্যবহার করে নিম্নলিখিত উদাহরণটি বিবেচনা করুন:

template<int N> 
void printBitset (std::bitset<N> const& bs) 
{ 
    std::cout << bs.template to_string<char,char_traits<char>, 
                                       allocator<char> >(); 
} 

এই উদাহরণে বিস্ময়কর গঠন .template হয়। টেমপ্লেটের অতিরিক্ত ব্যবহার ব্যতীত, সংকলকটি জানে না যে নীচের থেকে কম টোকেন (<) যা আসলে "" এর চেয়ে কম "নয় তবে একটি টেম্পলেট আর্গুমেন্ট তালিকার শুরু। মনে রাখবেন যে পিরিয়ডের পূর্বে নির্মাণ কোনও টেম্পলেট প্যারামিটারের উপর নির্ভর করে তবেই এটি একটি সমস্যা। আমাদের উদাহরণে, প্যারামিটার বিএস টেম্পলেট প্যারামিটার এন এর উপর নির্ভর করে।

উপসংহারে।

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