3 টি বড় সি ++ সংকলকগুলিতে প্রোগ্রামটি আলাদাভাবে সংকলিত হচ্ছে। কোনটি ঠিক?


116

আমার পূর্ববর্তী প্রশ্নের একটি আকর্ষণীয় ফলোআপ (যদিও বড় ব্যবহারিক গুরুত্বের সাথে নয়): কেন ভেরিয়েবল ঘোষণার সময় সি ++ আমাদের কেন বন্ধনীতে পরিবর্তনশীল নামটি ঘিরে রাখার অনুমতি দেয়?

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

নীচের প্রোগ্রামটি একবার দেখুন:

#include <iostream>
struct B
{
};

struct C
{
  C (){ std::cout << "C" << '\n'; }
  C (B *) { std::cout << "C (B *)" << '\n';}
};

B *y = nullptr;
int main()
{
  C::C (y);
}
  1. G ++ 4.9.2 দিয়ে সংকলন আমাকে নিম্নলিখিত সংকলন ত্রুটি দেয়:

    main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive]
  2. এটি MSVC2013 / 2015 এবং প্রিন্ট সহ সফলভাবে সংকলন করে C (B *)

  3. এটি ঝনঝন 3.5 এবং প্রিন্ট সহ সফলভাবে সংকলন করে C

সুতরাং বাধ্যতামূলক প্রশ্ন কোনটি সঠিক? :)

(আমি জোরালোভাবে ঝাঁকুনির সংস্করণের দিকে ছড়িয়ে পড়েছি যদিও এবং প্রযুক্তিগতভাবে টাইপডেফের সাথে টাইপ পরিবর্তন করার পরে ভেরিয়েবলের ঘোষণা বন্ধ করার জন্য এমএসভিসি উপায়টি একেবারেই অদ্ভুত বলে মনে হয়)


3
C::C y;মানে না, তাই না? উভয়েই C::C (y); প্রথমে আমি ভেবেছিলাম এটি মোস্ট-ভেক্সিং-পার্স স্ট্যাকওভারফ্লো. com/Qtionstions/tagged/ Most-vexing-parse এর উদাহরণ , তবে এখন আমি মনে করি এটি কেবল অপরিজ্ঞাত আচরণের অর্থ তিনটি সংকলক "সঠিক"।
ডেল উইলসন

4
# 3 ঝনঝন স্পষ্টভাবে ভুল, # 2 msvc খুব প্রশ্রয়ের এবং # 1 ছ ++, অধিকার ((আমি অনুমান) হল

8
C::Cকোনও ধরণের নাম এটি কোনও ফাংশনটির নাম দেয় না, তাই জিসিসি সঠিক ইমো।
গ্যালিক


উত্তর:


91

জিসিসি সঠিক, কমপক্ষে সি ++ 11 দেখার নিয়ম অনুসারে। ৩.৪.৩.১ [শ্রেণী.কোয়াল] / ২ উল্লেখ করে যে, যদি নেস্টেড নাম নির্দিষ্টকারক শ্রেণীর নামের সাথে একই হয় তবে এটি কনস্ট্রাক্টরকে ইনজেকশন শ্রেণীর নাম নয় refers এটি উদাহরণ দেয়:

B::A ba;           // object of type A
A::A a;            // error, A::A is not a type name
struct A::A a2;    // object of type A

এটা তোলে ফাংশন-শৈলী ঢালাই একটি অস্থায়ী তৈরি অভিব্যক্তি হিসাবে MSVC misinterprets এটা দেখে মনে হচ্ছে Cসঙ্গে yএকটি কন্সট্রাকটর প্যারামিটার হিসাবে; এবং কল্যাং এটিকে yপ্রকারভেদযুক্ত একটি পরিবর্তনশীল হিসাবে ঘোষণা হিসাবে ভুল ব্যাখ্যা করে C


2
হ্যাঁ, ৩.৪.৩.১/২ মূল কী। ভাল করেছ!
অরবিট

এতে বলা হয়েছে "এমন একটি অনুসন্ধানে যেখানে ফাংশনটির নাম উপেক্ষা করা হয় না"। আমার কাছে মনে হয় যে প্রদত্ত উদাহরণগুলিতে, বিশেষত A::A a;, ফাংশনের নামগুলি উপেক্ষা করা উচিত - না?
কলম্বো

1
N4296-তে সংখ্যাটি অনুসরণ করে কীটি সত্যই 3.4.3.1/2.1 হয়: "যদি নেস্টেড-নাম-নির্দিষ্টকরণকারীর পরে নির্দিষ্ট নামটি সিতে দেখা হয় তবে সি এর ইনজেক্টেড-শ্রেণি-নাম [...] নাম পরিবর্তে সি সি এর নির্মাতার নাম হিসাবে বিবেচনা করা হয়। " মাইকের সংক্ষিপ্তসারটি কিছুটা অতি সরল যদিও - উদাহরণস্বরূপ, শ্রেণীর নামের বর্গের নামের একটি টাইপডেফ শ্রেণীর নাম থেকে আলাদা কোনও নেস্টেড নাম নির্দিষ্টকারীকে এখনও শ্রেণীর নাম উল্লেখ করতে অনুমতি দেবে, সুতরাং এটি এখনও উল্লেখ করে ctor।
জেরি কফিন

2
@ ম্যাগেজ: প্রশ্ন থেকে: "এটি এমএসভিসি ২০১৩ / ২০১৫ এবং প্রিন্ট সহ সফলভাবে সংকলন করে C (B *)"
অরবিট

2
সম্পূর্ণতার জন্য এটি নির্ধারণ করা উচিত যে এটি ডায়াগনস্টিকের সাথে প্রয়োজনীয় নয়, বা কোনও ডায়াগনস্টিকের প্রয়োজন নেই এমন অসুস্থ। যদি পরে থাকে তবে সমস্ত সংকলক "সঠিক"।
এমএম

16

জি ++ সঠিক কারণ এটি একটি ত্রুটি দেয়। কারণ নির্মাতাকে newঅপারেটর ব্যতীত এ জাতীয় বিন্যাসে সরাসরি কল করা যায় না । এবং যদিও আপনার কোড কল করে তবে C::Cএটি দেখতে কোনও কনস্ট্রাক্টর কল বলে মনে হচ্ছে। তবে, সি ++ 11 স্ট্যান্ডার্ড 3.4.3.1 অনুসারে এটি কোনও আইনী ফাংশন কল বা কোনও প্রকারের নাম নয় ( মাইক সিমুরের উত্তর দেখুন )।

ঝাঁকুনি ভুল কারণ এটি এমনকি সঠিক ফাংশনটি কল করে না।

এমএসভিসি যুক্তিসঙ্গত কিছু তবে এটি এখনও মানটিকে অনুসরণ করে না।


2
newঅপারেটর কী পরিবর্তন করে?
নীল কিরক

1
@ নীলকির্ক: অনেক লোক, যারা মনে করেন যে new B(1,2,3)এটি একরকম "প্রত্যক্ষ নির্মাণকারীর কল" (যা অবশ্যই এটি অস্থায়ী ইনস্ট্যান্টেশন B(1,2,3)বা ঘোষণাপত্রের থেকে পৃথক নয়) B b(1,2,3)
অরবিট

@LightningRacisinObrit আপনি কিভাবে বর্ণনা করবেন কি new B(1,2,3)হয়?
ব্যবহারকারী 2030677

1
@ ব্যবহারকারী2030677: কীওয়ার্ড new, একটি প্রকারের নাম এবং একটি নির্মাণকারীর যুক্তি তালিকাটি ব্যবহার করে একটি নতুন এক্সপ্রেশন । এটি এখনও "সরাসরি নির্মাণকারী কল" নয়।
অরবিট

"ঝনঝনানি ভুল কারণ এটি এমনকি সঠিক ফাংশনটিও ডাকে না" ": আমি মনে করি (কারণ ঘোষণাপত্রের প্রথম বন্ধনী সম্পর্কে ওপির মন্তব্য) যা ক্ল্যাংকে ব্যাখ্যা C::C (y); করে C::C y;, অর্থাত সি এর ভেরিয়েবল y এর একটি সংজ্ঞা (ইনজেকশন টাইপ সি ব্যবহার করে: : সি ভুলভাবে ক্রমবর্ধমান উন্মাদ ভাষা স্পেসিফিকেশন এর 3.4.1,2 উপেক্ষা করে যা সি :: সি নির্মাণকারীকে তৈরি করে)। ইমো, যেমনটি আপনি ভাবেন বলে মনে হচ্ছে তেমন তাত্পর্যপূর্ণ ত্রুটি নয়।
পিটার - মনিকা 20
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.