SFINAE বিভিন্ন সংকলক সহ ভয়েডটি ব্যবহার করে বিভিন্ন ফলাফলের দিকে নিয়ে যায়


10

নিম্নলিখিত কোড বিবেচনা করুন:

template <typename T> using VoidT = void;

class A {
public:
   using TEST = int;
};

class C {
public:
   using DIFFERENT = int;
};

template <typename T, typename Enable = void>
class B {
public:
   B() = delete;
};

template <typename T>
class B<T, VoidT<typename T::TEST>> {
public:
   B() = default;
};

template <typename T>
class B<T, VoidT<typename T::DIFFERENT>> {
public:
   B() = default;
};

int main() {
   B<A> a;
   B<C> b;

   return 0;
}

এই কোডটি সংকলন করে g ++ - 4.8.5 ব্যবহার করে আমাকে নিম্নলিখিত ত্রুটি বার্তাটি দেয়:

~/test/compile_test> g++ -std=c++11 test.cpp

test.cpp:31:7: error: redefinition of ‘class B<T, void>’

test.cpp:24:7: error: previous definition of ‘class B<T, void>’

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

উত্তর:


9

এটি কি জিসিসিতে কোনও বাগ ছিল যা ঠিক করা হয়েছিল?

এটা মান একটি ত্রুটি ছিল। এটি পূর্ববর্তী স্ট্যান্ডার্ড সংস্করণগুলির জন্য পূর্ববর্তী অবস্থায় সংশোধন করা হয়েছিল তবে অবশ্যই কেবলমাত্র নতুন সংকলক সংস্করণগুলির মধ্যে এটির সমাধান হবে। এটি সিডাব্লুজি ইস্যু 1558 ছিল এবং এটি থেকে উদ্ধৃত করা:

একটি উলামের টেম্পলেট বিশেষায়নের মধ্যে অব্যক্ত যুক্তিগুলির চিকিত্সা 17.6.7 [টেম্পালিওস] এর বর্তমান শব্দ দ্বারা নির্দিষ্ট করা হয়নি। উদাহরণ স্বরূপ:

  #include <iostream>

  template <class T, class...>
    using first_of = T;

  template <class T>
    first_of<void, typename T::type> f(int)
      { std::cout << "1\n"; }

  template <class T>
    void f(...)
      { std::cout << "2\n"; }

  struct X { typedef void type; };

  int main() {
    f<X>(0);
    f<int>(0);
  }

টি সহ প্রথম_এর রেফারেন্সটি কি কেবল শূন্যের সমতুল্য, বা এটি কোনও বিকল্প ব্যর্থতা?

ডিআর ফিক্স ব্যতীত সংকলকগণের জন্য কাজটি হেল্পার ব্যবহারের জন্য:

template<typename T> struct voider { using type = void; };
template <typename T> using VoidT = typename voider<T>::type;

প্রতিস্থাপনের ব্যর্থতা কোনও শ্রেণির টেম্পলেটে গ্যারান্টিযুক্ত।


1
প্রতিশোধমূলক সমাধানগুলি আমাকে বিরক্ত করে। এর অর্থ ভাষাটির কোনও সংস্করণ বর্ণিত কোনও প্রামাণ্য দলিল নেই।
অরবিটে

2
@ লাইটনেসেসেসিনআরবিট - আমি আপনার বক্তব্যটি দেখছি। যে কেউ প্রত্যাশা করতে পারে যে এই ধরনের প্রত্যাবর্তনমূলক সমাধানগুলি কেবলমাত্র বৈধ নির্মাণের জন্যই সংরক্ষিত রয়েছে যা প্রত্যাখ্যান করা উচিত নয়, সুতরাং ক্ষতির পরিমাণটি সর্বনিম্ন।
গল্পগ্রাহক - আনস্ল্যান্ডার মনিকা

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