অপারেটর অগ্রাধিকার ব্যতীত অতিরিক্ত বন্ধনীগুলির কখন প্রভাব থাকে?


91

সি ++ এ প্যারেন্থিসগুলি অনেক জায়গায় ব্যবহৃত হয়: যেমন ফাংশন কল এবং গোষ্ঠীভুক্তকরণে অপারেটরের অগ্রাধিকারকে ওভাররাইড করার জন্য। অবৈধ অতিরিক্ত বন্ধনী (যেমন ফাংশন কল আর্গুমেন্ট তালিকার চারপাশে) বাদে সি ++ এর একটি সাধারণ-নিরঙ্কুশ-নিয়মটিও নয় যে অতিরিক্ত বন্ধনী কখনই আঘাত করে না :

5.1 প্রাথমিক এক্সপ্রেশন [এক্সপ্রেসপ্রিম]

৫.১.১ সাধারণ [expr.prim.general]

A একটি প্রথম বন্ধনীযুক্ত প্রকাশটি এমন একটি প্রাথমিক ভাব যা এর প্রকার এবং মান বদ্ধ প্রকাশের মতই those অনুষঙ্গগুলির উপস্থিতি প্রভাবটি প্রভাবিত করে না যা অভিব্যক্তিটি খুব কম। বন্ধুত্বযুক্ত এক্সপ্রেশনটি ঠিক একই প্রসঙ্গে ব্যবহার করা যেতে পারে যেখানে আবদ্ধ অভিব্যক্তিটি ব্যবহার করা যেতে পারে, এবং একই অর্থ ব্যতীত অন্যভাবে নির্দেশিত ব্যতীত

প্রশ্ন : বেসিক অপারেটর অগ্রাধিকারকে ওভার্রাইডিং ব্যতীত অতিরিক্ত কোন বন্ধনী সি ++ প্রোগ্রামের অর্থ পরিবর্তন করে?

দ্রষ্টব্য : আমি পয়েন্টার-থেকে-সদস্য সিন্টেক্সের সীমাবদ্ধতাটিকে &qualified-idবন্ধনী ছাড়াই বিবেচনা করাকে সুযোগের বাইরে বলে মনে করি কারণ এটি দুটি অর্থের বাক্যকে পৃথক অর্থের পরিবর্তে সিনট্যাক্সকে সীমাবদ্ধ করে । একইভাবে, প্রিপ্রোসেসর ম্যাক্রো সংজ্ঞায়নের মধ্যে প্রথম বন্ধনী ব্যবহার অযাচিত অপারেটর অগ্রাধিকার থেকেও রক্ষা করে।


"আমি পয়েন্টার-টু-সদস্যকে অপারেটর অগ্রাধিকারের একটি প্রয়োগ হিসাবে & (যোগ্য-আইডি) রেজোলিউশনটিকে বিবেচনা করি" " - কেন? আপনি যদি প্রথম বন্ধনীর কথা বাদ দেন &(C::f), অপরেন্ডটি &এখনও আছে C::f, তাই না?

@ এইচভিডি expr.unary.op/4: সদস্যের কাছে পয়েন্টার কেবল তখনই তৈরি হয় যখন স্পষ্টভাবে &ব্যবহৃত হয় এবং এর অপারেন্ডটি একটি যোগ্য-আইডি হয় যা বন্ধনীতে আবদ্ধ থাকে না।
TemplateRex

ঠিক আছে, তাই অপারেটর অগ্রাধিকার সঙ্গে কি আছে? (কোনও বিষয় নয়, আপনার সম্পাদিত প্রশ্ন

@hvd আপডেট, আমি LHS সঙ্গে RHS বিভ্রান্তিকর ছিল এই Q & A- , এবং ডান বন্ধনী ফাংশন কল এর প্রাধান্য ওভাররাইড করার জন্য ব্যবহার করা হয় ()পয়েন্টার টু সদস্য নির্বাচক উপর::*
TemplateRex

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

উত্তর:


113

টিএল; ডিআর

অতিরিক্ত বন্ধনীগুলি নিম্নলিখিত প্রসঙ্গে একটি C ++ প্রোগ্রামের অর্থ পরিবর্তন করে:

  • যুক্তি-নির্ভর নাম অনুসন্ধান প্রতিরোধ করা
  • তালিকা প্রসঙ্গে কমা অপারেটরকে সক্ষম করা
  • ভেক্সিং পার্সের অস্পষ্টতার সমাধান
  • decltypeঅভিব্যক্তি রেফারেন্স বিবেচনা
  • প্রিপ্রসেসর ম্যাক্রো ত্রুটি প্রতিরোধ করা

যুক্তি-নির্ভর নাম অনুসন্ধান রোধ করা হচ্ছে

স্ট্যান্ডার্ডের এনেেক্স এ-তে যেমন বর্ণনা করা আছে, post-fix expressionফর্মের (expression)একটি হ'ল একটি primary expression, তবে একটি নয় id-expressionএবং তাই একটি নয় unqualified-id। এর অর্থ হ'ল (fun)(arg)প্রচলিত ফর্মের তুলনায় ফর্মের ফাংশন কলগুলিতে যুক্তি-নির্ভর নাম অনুসন্ধানটি প্রতিরোধ করা হয়েছে fun(arg)

৩.৪.২ যুক্তি-নির্ভর নাম অনুসন্ধান [বেসিক.লুপআপ.আরগডিপ]

1 যখন কোনও ফাংশন কলের (5.2.2) পোস্টফিক্স-এক্সপ্রেশনটি একটি অযোগ্য-আইডি হয় , তখন সাধারণ অসমর্থিত অনুসন্ধানের (3.4.1) সময় বিবেচনা করা হয়নি এমন অন্যান্য নেমস্পেসগুলি অনুসন্ধান করা যেতে পারে এবং সেই নামগুলির মধ্যে নেমস্পেস-স্কোপ বন্ধু ফাংশন বা ফাংশন টেম্পলেট ঘোষণাগুলি (১১.৩) অন্যথায় দৃশ্যমান নয় এমনটি পাওয়া যেতে পারে। অনুসন্ধানে এই পরিবর্তনগুলি আর্গুমেন্টের ধরণের (এবং টেমপ্লেট টেম্পলেট আর্গুমেন্টগুলির জন্য, টেমপ্লেট আর্গুমেন্টের নামের জায়গার উপর) নির্ভর করে। [উদাহরণ:

namespace N {
    struct S { };
    void f(S);
}

void g() {
    N::S s;
    f(s);   // OK: calls N::f
    (f)(s); // error: N::f not considered; parentheses
            // prevent argument-dependent lookup
}

এর উদাহরণ]

তালিকা প্রসঙ্গে কমা অপারেটরটিকে সক্ষম করা

কমা অপারেটরের বেশিরভাগ তালিকার মতো প্রসঙ্গে (ফাংশন এবং টেম্পলেট আর্গুমেন্ট, ইনিশিয়ালাইজার তালিকা ইত্যাদি) এর একটি বিশেষ অর্থ রয়েছে। এই a, (b, c), dজাতীয় প্রসঙ্গে ফর্মের প্যারেন্টিহেসগুলি নিয়মিত ফর্মের তুলনায় কমা অপারেটরকে সক্ষম করতে পারে a, b, c, dযেখানে কমা অপারেটর প্রয়োগ করে না।

5.18 কমা অপারেটর [expr.comma]

২ প্রসঙ্গে যেখানে কমাটিকে একটি বিশেষ অর্থ দেওয়া হয়, [উদাহরণস্বরূপ: ফাংশনগুলিতে আর্গুমেন্টের তালিকায় (5.2.2) এবং ইনিশিয়ালাইজারের তালিকায় (8.5) এবং উদাহরণস্বরূপ] ক্লজ 5 এ বর্ণিত কমা অপারেটরটি কেবল প্রথম বন্ধনীতে উপস্থিত হতে পারে। [উদাহরণ:

f(a, (t=3, t+2), c);

তিনটি আর্গুমেন্ট রয়েছে, যার দ্বিতীয়টির মান রয়েছে —.আর উদাহরণ হিসাবে]

ভেক্সিং পার্সের অস্পষ্টতা রেজোলিউশন

সি এবং এর আরকেইন ফাংশন ডিক্লেয়ারেশন সিনট্যাক্সের সাথে পশ্চাদগম্য সামঞ্জস্যতা আশ্চর্যজনক পার্সিং অস্পষ্টতাকে ডেকে আনতে পারে, যা ভেক্সিং পার্স হিসাবে পরিচিত। মূলত, ঘোষণাপত্র হিসাবে বিশ্লেষণযোগ্য যে কোনও কিছুকে একটি হিসাবে পার্স করা হবে , যদিও প্রতিযোগী পার্সও প্রয়োগ হবে।

8.৮ দ্ব্যর্থহীনতা রেজোলিউশন [stmt.ambig]

1 ব্যাকরণের একটি অভিব্যক্তি-বিবৃতি এবং ঘোষণার সাথে জড়িত রয়েছে : একটি ফাংশন-স্টাইলের সুস্পষ্ট ধরণের রূপান্তর (5.2.3) সহ একটি এক্সপ্রেশন-বিবৃতি তার বামতম সাফল্যের এক্সপ্রেশনটি কোনও ঘোষণার থেকে পৃথক হতে পারে যেখানে প্রথম ঘোষক একটি দিয়ে শুরু হয় ( । সেসব ক্ষেত্রে বিবৃতি ঘোষণা হয়

৮.২ অস্পষ্টতা রেজোলিউশন [dcl.ambig.res]

1 একটি ফাংশন-স্টাইলের castালাই এবং 8.৮-এ উল্লিখিত একটি ঘোষণার মধ্যে সাদৃশ্য থেকে উদ্ভূত অস্পষ্টতা একটি ঘোষণার প্রসঙ্গেও ঘটতে পারে । সেই প্রসঙ্গে, পছন্দটি একটি প্যারামিটার নামের চারপাশে বন্ধনীগুলির রিডানড্যান্ট সেট এবং আরম্ভকারী হিসাবে ফাংশন-শৈলীর castালাই সহ কোনও অবজেক্ট ঘোষণার মধ্যে ফাংশন ঘোষণার মধ্যে রয়েছে। ঠিক 6..৮-তে বর্ণিত অস্পষ্টতাগুলির জন্য, রেজোলিউশনে এমন কোনও নির্মাণকে বিবেচনা করা হবে যা সম্ভবত ঘোষণা ঘোষণা হতে পারে । [দ্রষ্টব্য: একটি ঘোষণাকে স্পষ্টরূপে একটি ননফানশন-স্টাইলের কাস্ট দ্বারা, সূচনাটি নির্দেশ করতে একটি = দ্বারা বা পরামিতি নামের কাছাকাছি রিডানড্যান্ট প্রথম বন্ধনী মুছে ফেলা যেতে পারে। Note সংক্ষেপে নোট] [উদাহরণ:

struct S {
    S(int);
};

void foo(double a) {
    S w(int(a));  // function declaration
    S x(int());   // function declaration
    S y((int)a);  // object declaration
    S z = int(a); // object declaration
}

এর উদাহরণ]

এর একটি বিখ্যাত উদাহরণ হ'ল মোস্ট ভেক্সিং পার্স , এটি তাঁর কার্যকর এসটিএল বইয়ের আইটেম 6-এ স্কট মায়ার্স দ্বারা জনপ্রিয় :

ifstream dataFile("ints.dat");
list<int> data(istream_iterator<int>(dataFile), // warning! this doesn't do
               istream_iterator<int>());        // what you think it does

এটি একটি ফাংশন ঘোষণা করে data, যার রিটার্ন টাইপ list<int>। ফাংশন ডেটা দুটি পরামিতি লাগে:

  • প্রথম প্যারামিটারটির নাম দেওয়া হয়েছে dataFile। এটি টাইপ হয় istream_iterator<int>। আশেপাশের প্রথম বন্ধনীগুলি dataFileঅতিরিক্ত অতিরিক্ত এবং এড়ানো হয় and
  • দ্বিতীয় প্যারামিটারটির কোনও নাম নেই। এর প্রকারটি কিছুই না নিয়ে এবং একটি ফেরত ফাংশনটির পয়েন্টার istream_iterator<int>

প্রথম ফাংশন আর্গুমেন্টের চারপাশে অতিরিক্ত প্রথম বন্ধনী স্থাপন করা (দ্বিতীয় যুক্তির আশেপাশে প্রথম বন্ধনী অবৈধ) অস্পষ্টতার সমাধান করবে

list<int> data((istream_iterator<int>(dataFile)), // note new parens
                istream_iterator<int>());          // around first argument
                                                  // to list's constructor

সি ++ 11 এর ব্রেস-ইনিশিয়ালাইজার সিনট্যাক্স রয়েছে যা অনেক প্রসঙ্গে যেমন পার্সিংয়ের সমস্যাগুলি সাইড-স্টেপ করতে দেয়।

মধ্যে referenceness Deducing decltypeএক্সপ্রেশন

autoটাইপ ছাড়ের বিপরীতে , decltypeরেফারেন্স (মান এবং মূল্য রেফারেন্স) কেটে নেওয়া যায়। বিধি decltype(e)এবং decltype((e))এক্সপ্রেশন মধ্যে নিয়ম পার্থক্য :

.1.১.২.২ সরল প্রকারের নির্দিষ্টকরণকারী [dcl.type.simple]

4 একটি অভিব্যক্তির জন্য e, দ্বারাdecltype(e) বর্ণিত ধরণটি নিম্নলিখিত হিসাবে সংজ্ঞায়িত করা হয়েছে:

- যদি eকোনও অপ্রতীকৃত আইডি-এক্সপ্রেশন বা একটি অপ্রাপ্তবিত্ত শ্রেণীর সদস্য অ্যাক্সেস (5.2.5) decltype(e)হয় তবে এটির নাম অনুসারে সত্তার প্রকার e। যদি এই জাতীয় কোনও সত্ত্বা না থাকে, বা eঅতিরিক্ত লোড ফাংশনগুলির একটি সেটটির নাম দেওয়া হয়, প্রোগ্রামটি খারাপভাবে গঠিত;

- অন্যথায়, যদি eএকটি xvalue হয়, decltype(e)হয় T&&, যেখানে Tপ্রকার e;

- অন্যথায়, যদি eএকটি লভ্যালু decltype(e)হয় T&, হয় যেখানে Tপ্রকার e;

- অন্যথায়, decltype(e)এর ধরণ e

ডিক্লাইপ স্পেসিফায়ারের অপারেন্ডটি একটি মূল্যহীন অপারেন্ড (ক্লজ 5)। [উদাহরণ:

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 0;   // type is const int&&
decltype(i) x2;           // type is int
decltype(a->x) x3;        // type is double
decltype((a->x)) x4 = x3; // type is const double&

Exampleend উদাহরণ] [দ্রষ্টব্য: জড়িত প্রকারগুলি নির্ধারণের জন্য বিধিগুলি decltype(auto)7.1.6.4 এ নির্দিষ্ট করা আছে। অন্তর্ভুক্ত নোট]

decltype(auto)প্রারম্ভিক অভিব্যক্তিটির আরএইচএসে অতিরিক্ত বন্ধনীগুলির জন্য বিধিগুলির একই অর্থ। এখানে C ++ FAQ এবং এই সম্পর্কিত প্রশ্নোত্তর থেকে একটি উদাহরণ দেওয়া আছে

decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; }  //A
decltype(auto) look_up_a_string_2() { auto str = lookup1(); return(str); } //B

প্রথম রিটার্ন string, দ্বিতীয় রিটার্ন string &, যা স্থানীয় ভেরিয়েবলের একটি রেফারেন্স str

প্রিপ্রসেসর ম্যাক্রো সম্পর্কিত ত্রুটিগুলি রোধ করা হচ্ছে

সি ++ ভাষার সাথে যথাযথ যোগাযোগের ক্ষেত্রে প্রিপ্রোসেসর ম্যাক্রোগুলির একটি সূক্ষ্মতা রয়েছে যার মধ্যে সবচেয়ে সাধারণ নীচে তালিকাবদ্ধ রয়েছে

  • #define TIMES(A, B) (A) * (B);অযাচিত অপারেটর অগ্রাধিকার এড়াতে ম্যাক্রো সংজ্ঞাটির অভ্যন্তরে ম্যাক্রো প্যারামিটারগুলির আশেপাশে বন্ধনী ব্যবহার করা (উদাহরণস্বরূপ TIMES(1 + 2, 2 + 1)যার ফলন 9 হয় তবে আশেপাশে প্রথম বন্ধনী ছাড়াই 6 পাওয়া যায় (A)এবং(B)
  • ম্যাক্রো আর্গুমেন্টের ভিতরে কমা রয়েছে তার আশেপাশে প্রথম বন্ধনী ব্যবহার করা: assert((std::is_same<int, int>::value));যা অন্যথায় সংকলন করবে না
  • অন্তর্ভুক্ত শিরোনামগুলিতে ম্যাক্রো সম্প্রসারণ থেকে রক্ষা করার জন্য একটি ফাংশনটির চারপাশে প্রথম বন্ধনী ব্যবহার করা: (min)(a, b)(এডিএলকে অক্ষম করার অযাচিত পার্শ্ব প্রতিক্রিয়া সহ)

7
সত্যিই প্রোগ্রাম অর্থ অনুশীলন পরিবর্তন হয় না, কিন্ত সবচেয়ে ভাল এবং সতর্কবার্তা কম্পাইলার দ্বারা নির্গত প্রভাবিত: অতিরিক্ত প্রথম বন্ধনী ব্যবহার করা উচিত if/ whileযদি অভিব্যক্তি একটি কাজ নয়। যেমন if (a = b)- সতর্কতা (আপনি কি বোঝাতে চেয়েছিলেন ==?), যদিও if ((a = b))- কোনও সতর্কতা নেই।
সিএসকিউ

@ সিএসকিউ ধন্যবাদ, ভাল পর্যবেক্ষণ, তবে এটি একটি নির্দিষ্ট সংকলক দ্বারা সতর্কবার্তা এবং মানক দ্বারা বাধ্যতামূলক নয়। আমি মনে করি না যে এই প্রশ্নোত্তরের ভাষা-আইনী প্রকৃতির মধ্যে এটি খাপ খায়।
TemplateRex

কি (min)(a, b)(মন্দ ম্যাক্রো সঙ্গে min(A, B)) যুক্তি নির্ভর নাম লুকআপ প্রতিরোধের অংশ?
জারোড 42

@ Jarod42 আমি তাই অনুমান, কিন্তু এর এই ধরনের বিবেচনা করি এবং অন্যান্য মন্দ ম্যাক্রো প্রশ্ন আওতার বাইরে হতে :-)
TemplateRex

4
@ জামেসকাঞ্জ: নোট করুন যে ওপি এবং টেমপ্লেক্স একই ব্যক্তি ^ _ ^
জারোড 42

4

সাধারণভাবে, প্রোগ্রামিং ভাষায়, "অতিরিক্ত" বন্ধনীগুলি বোঝায় যে তারা সিনট্যাক্টিকাল পার্সিং ক্রম বা অর্থ পরিবর্তন করছে না । কোড পড়ার সুবিধার জন্য তাদের অর্ডার (অপারেটর অগ্রাধিকার) পরিষ্কার করার জন্য যুক্ত করা হচ্ছে এবং তাদের একমাত্র প্রভাবটি সংকলন প্রক্রিয়াটি সামান্য করা এবং কোড বোঝার ক্ষেত্রে মানুষের ত্রুটিগুলি হ্রাস করা সম্ভব হবে (সম্ভবত সামগ্রিক বিকাশের প্রক্রিয়াটিকে ত্বরান্বিত করবে) )।

যদি প্রথম বন্ধনীর সেটগুলি একটি এক্সপ্রেশনকে বিশ্লেষণের পদ্ধতি পরিবর্তন করে তবে সেগুলি সংজ্ঞায়িত করে অতিরিক্ত হয় না । অবৈধ / অবৈধ পার্সকে আইনী হিসাবে রূপান্তরকারী প্যারেন্টিহেসগুলি "অতিরিক্ত" নয়, যদিও এটি একটি দুর্বল ভাষার নকশা চিহ্নিত করতে পারে


4
ঠিক যেমন, এবং এটি সি ++ তেও সাধারণ নিয়ম (প্রশ্নে স্ট্যান্ডার্ড উক্তিটি দেখুন), অন্যথায় নির্দেশিত ব্যতীত । এই "দুর্বলতাগুলি" চিহ্নিত করা এই প্রশ্নোত্তরের উদ্দেশ্য ছিল।
TemplateRex
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.