অ-স্থিতিশীল ডেটা সদস্য এবং নেস্টেড ক্লাস কনস্ট্রাক্টরের ক্লাস ইনিশিয়ালাইজেশন ব্যবহার করার সময় ত্রুটি


90

নিম্নলিখিত কোডটি বেশ তুচ্ছ এবং আমি প্রত্যাশা করেছি যে এটি জরিমানা সংকলন করা উচিত।

struct A
{
    struct B
    {
        int i = 0;
    };

    B b;

    A(const B& _b = B())
        : b(_b)
    {}
};

আমি এই কোডটি জি ++ সংস্করণ 4.7.2, 4.8.1, ঝাঁকুনি ++ 3.2 এবং 3.3 দিয়ে পরীক্ষা করেছি। এই কোডটিতে g ++ 4.7.2 সেগফাল্টগুলি ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770 ) ছাড়াও অন্যান্য পরীক্ষিত সংকলকরা ত্রুটি বার্তা দেয় যা খুব বেশি ব্যাখ্যা করে না।

g ++ 4.8.1:

test.cpp: In constructor ‘constexpr A::B::B()’:
test.cpp:3:12: error: constructor required before non-static data member for ‘A::B::i’ has been parsed
     struct B
            ^
test.cpp: At global scope:
test.cpp:11:23: note: synthesized method ‘constexpr A::B::B()’ first required here 
     A(const B& _b = B())
                       ^

ঝনঝন ++ 3.2 এবং 3.3:

test.cpp:11:21: error: defaulted default constructor of 'B' cannot be used by non-static data member initializer which appears before end of class definition
    A(const B& _b = B())
                    ^

এই কোডটি সংকলনযোগ্য করা সম্ভব এবং মনে হয় এটির কোনও পার্থক্য করা উচিত নয়। দুটি বিকল্প রয়েছে:

struct B
{
    int i = 0;
    B(){} // using B()=default; works only for clang++
};

বা

struct B
{
    int i;
    B() : i(0) {} // classic c++98 initialization
};

এই কোডটি কি সত্যই ভুল বা সংকলকগুলি ভুল?


4
আমার জি ++ 4.7.3 internal compiler error: Segmentation faultএই কোডটি বলেছেন ...
ফ্রেড ফু

4
(ত্রুটি C2864: 'এ :: বি :: আই': কেবল স্ট্যাটিক কনস্ট ইন্টিগ্রাল ডেটা সদস্যদের একটি শ্রেণীর মধ্যেই আরম্ভ করা যেতে পারে) ভিসি 2010 যা বলেছে। এই আউটপুট g ++ সঙ্গে একমত। ঝাঁকুনি এটি খুব কম বোঝায় যদিও এটি বলে says আপনি স্ট্রাক্টে কোনও ভেরিয়েবল ডিফল্ট করতে পারবেন না int i = 0যদি না হয় static const int i = 0
ক্রিস কুপার

@ বরগালিডার: বিটিডাব্লু আমি কোনও B()কনস্ট্রাক্টরের কাছে ফাংশন কল হিসাবে অভিব্যক্তিটি ভাবার প্রলোভন এড়াতে চাই । আপনি কখনই কোনও কনস্ট্রাক্টরকে সরাসরি "কল" করেন না । এটিকে বিশেষ সিনট্যাক্স হিসাবে ভাবেন যা একটি অস্থায়ী তৈরি করে B... এবং নির্মাণকারীকে প্রক্রিয়াটির কেবলমাত্র একটি অংশ হিসাবে অনুসরণ করা হয়, এটি মেকানিজমের মধ্যে গভীরভাবে অনুসরণ করা হয়।
2'13

4
হুঁ, একটি নির্মাণকারী যুক্ত করে Bমনে হচ্ছে এই কাজটি করা হচ্ছে gcc 4.7
শফিক ইয়াঘমোর

7
মজার বিষয় হল, এ এর ​​নির্মাতার সংজ্ঞাটিকে এ এর ​​বাইরে সরিয়ে নেওয়াও এটি (g ++ 4.7) কাজ করে বলে মনে হচ্ছে; "ডিফল্ট ডিফল্ট কনস্ট্রাক্টর সহ কোন চিমগুলি ব্যবহার করা যায় না ... শ্রেণীর সংজ্ঞা শেষ হওয়ার আগে"।
16:25 এ চাঁদ শ্যাও

উত্তর:


84

এই কোডটি কি সত্যই ভুল বা সংকলকগুলি ভুল?

ভাল, না। স্ট্যান্ডার্ডটির একটি ত্রুটি রয়েছে - এটি উভয়ই বলে যে Aএটি আরম্ভকারীকে পার্স করার সময় সম্পূর্ণ বিবেচিত হয় B::iএবং এটি B::B()(যা আরম্ভকারীকে ব্যবহার করে B::i) এর সংজ্ঞা অনুসারে ব্যবহার করা যেতে পারে A। এটি পরিষ্কারভাবে চক্রাকার। এই বিবেচনা:

struct A {
  struct B {
    int i = (A(), 0);
  };
  A() noexcept(!noexcept(B()));
};

এই অসঙ্গতি রয়েছে: B::B()পরোক্ষভাবে হয় noexceptiff A()নিক্ষেপ না, এবং A()নিক্ষেপ না iff B::B()হয় না noexcept । এই অঞ্চলে অন্যান্য অনেকগুলি চক্র এবং বৈপরীত্য রয়েছে।

এটি 1360 এবং 1397 মূল ইস্যু দ্বারা ট্র্যাক করা হয়েছে । কোর ইস্যুতে বিশেষত এই নোটটি 1397:

সম্ভবত এটিকে সম্বোধনের সর্বোত্তম উপায় হ'ল এটি কোনও অ-স্থিতিশীল ডেটা মেম্বার ইনিশিয়ালাইজারকে তার শ্রেণীর একজন খেলাপী কন্সট্রাক্টর ব্যবহার করার জন্য এটির দুর্গন্ধযুক্ত করে তোলে।

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

    A(const B& _b = B())
                    ^

... কারণ ক্ল্যাংটি ডিফল্ট আরম্ভকারীদের পার্স করার আগেই ডিফল্ট তর্কগুলি পার্স করে এবং এই ডিফল্ট যুক্তিটির Bডিফল্ট ইনিশিয়েলাইজারদের ইতিমধ্যে পার্স করা আবশ্যক (স্পষ্টভাবে সংজ্ঞায়িত করার জন্য B::B())।


জানা ভাল. তবে ত্রুটি বার্তাটি এখনও বিভ্রান্তিমূলক, যেহেতু কনস্ট্রাক্টর আসলে "অ স্থিতিশীল ডেটা মেম্বার ইনিশিয়ালাইজার দ্বারা ব্যবহৃত হয়" না।
aschepler

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

এই বিস্তারিত উত্তরের জন্য +1। তাহলে উপায় কি হবে? কিছু ধরণের "২-পর্যায়ের শ্রেণি পার্সিং", যেখানে অভ্যন্তরীণ শ্রেণীর উপর নির্ভরশীল বাহ্যিক শ্রেণীর সদস্যদের পার্সিংয়ের অভ্যন্তরীণ শ্রেণিগুলি সম্পূর্ণরূপে গঠিত না হওয়া পর্যন্ত বিলম্ব হয়?
TemplateRex

4
@ এসচেপলার হ্যাঁ, এখানে ডায়াগোনস্টিক খুব ভাল নয়। আমি তার জন্য llvm.org/PR16550 দায়ের করেছি।
রিচার্ড স্মিথ

@ কর্নস্টালक्स আমি ক্ল্যাংয়ের অ-স্থিতিশীল ডেটা সদস্যদের জন্য আরম্ভকারী প্রয়োগের সময় এই সমস্যাটি আবিষ্কার করেছি।
রিচার্ড স্মিথ

0

হয়তো এই সমস্যা হয়:

§12.1 5. একটি ডিফল্ট কনস্ট্রাক্টর যা ডিফল্ট হয় এবং মুছে ফেলা হিসাবে সংজ্ঞায়িত হয় না তা স্পষ্টভাবে সংজ্ঞায়িত হয় যখন এটি ক্লাসের ধরণের (1.8) কোনও অবজেক্ট তৈরি করতে অদ্ভুতভাবে ব্যবহৃত হয় (1.8) বা এটি প্রথম ঘোষণার পরে স্পষ্টতই খেলাপি হয়

সুতরাং, প্রথম দেখাতে গেলে ডিফল্ট কনস্ট্রাক্টর তৈরি করা হয়, তবে লুক ব্যর্থ হবে কারণ A সম্পূর্ণরূপে সংজ্ঞায়িত হয়নি এবং A এর ভিতরে B এর সন্ধান করা হবে না।


আমি "তাই" সম্পর্কে নিশ্চিত নই। স্পষ্টত B bকোনও সমস্যা নয় এবং স্পষ্ট পদ্ধতিতে / স্পষ্টভাবে ঘোষিত নির্মাতা খুঁজে Bপাওয়া কোনও সমস্যা নয়। সুতরাং এখানে কারণ অনুসন্ধানের জন্য আলাদাভাবে এগিয়ে যাওয়া উচিত তার কিছু সংজ্ঞা দেখতে পারা ভাল লাগবে যাতে এই কারণে আমরা কোডটি অবৈধ ঘোষণা করতে পারার আগে কেবল এই এক ক্ষেত্রে " Bঅভ্যন্তরীণ Aসন্ধান পাওয়া যায়" তবে অন্যদের নয় not
চাঁদ

আমি স্ট্যান্ডার্ডে শব্দগুলি পেয়েছি যে ক্লাস সংজ্ঞাটি নেস্টেড ক্লাসগুলির মধ্যে সহ-শ্রেণিকেন্দ্রিককরণের সময় সম্পূর্ণ বিবেচনা করা হয়। প্রসঙ্গটি প্রাসঙ্গিক বলে মনে হচ্ছে না বলে আমি রেকর্ড করতে বিরক্ত করিনি।
মার্ক

@ মমশ্যাডো: বিবৃতিতে বলা হয়েছে যে সুস্পষ্টভাবে ডিফল্ট নির্মাতারা নির্ধারিত হয় যখন অদ্ভুত ব্যবহার হয়। স্পষ্টভাবে প্রথম ঘোষণার পরে সংজ্ঞায়িত করা হয়। এবং বি বি কোনও কনস্ট্রাক্টরকে কল করে না, বি এর কল কন্সট্রাক্টরের
কনস্ট্রাক্টর

যদি ভালো কিছু সমস্যা ছিল, কোড এখনও অবৈধ বলে যদি আপনি সরাতে হবে =0থেকে i = 0;। তবে তা ব্যতীত =0কোডটি বৈধ এবং আপনি কোনও একটি সংকলক পাবেন না B()যা সংজ্ঞাটির মধ্যে ব্যবহারের বিষয়ে অভিযোগ করে A
aschepler
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.