سؤال

class Foo {
  public:
  explicit Foo(double item) : x(item) {}

  operator double() {return x*2.0;}

  private:
  double x;
}

double TernaryTest(Foo& item) {
  return some_condition ? item : 0;
}

Foo abc(3.05);
double test = TernaryTest(abc);

في المثال أعلاه, لماذا هو اختبار يساوي 6 (بدلا من 6.1) إذا some_condition هو صحيح ؟

تغيير التعليمات البرمجية مثل أدناه ترجع القيمة 6.1

double TernaryTest(Foo& item) {
  return some_condition ? item : 0.0; // note the change from 0 to 0.0
}

يبدو أن (في المثال الأصلي) قيمة الإرجاع من فو::مشغل مزدوج هو يلقي الباحث ومن ثم العودة إلى مضاعفة.لماذا ؟

هل كانت مفيدة؟

المحلول

والمشغل الشرطي يتحقق التحويلات في كلا الاتجاهين. في هذه الحالة، منذ منشئ الخاص بك هو واضح (حتى ?: ليس غامضة)، ويستخدم التحويل من Foo إلى int، وذلك باستخدام وظيفة التحويل الذي يحول إلى double: هذا يعمل، لأنه بعد تطبيق وظيفة التحويل، تحويل القياسية تحويل double إلى int (اقتطاع) التالي. نتيجة ?: في قضيتك int، ولها 6 القيمة.

في الحالة الثانية، منذ المعامل ديه اكتب double، لا يوجد مثل هذا التحويل زائدة لint يحدث، وبالتالي نوع نتيجة ?: ديه اكتب double مع القيمة المتوقعة.

لفهم التحويلات "غير ضرورية"، عليك أن تفهم أن عبارات مثل ?: الخاص بك يتم تقييم "السياق خالية": عند تحديد قيمة ونوع منه، والمترجم لا يعتبر أنه من المعامل لreturn لوظيفة إرجاع double.


وتحرير: ماذا يحدث إذا منشئ الخاص بك هو ضمني ؟ فإن التعبير ?: تكون غامضة، لأنه يمكنك تحويل int إلى rvalue من نوع Foo (باستخدام منشئ)، وFoo إلى rvalue من نوع int (باستخدام وظيفة التحويل). يقول ستاندرد

<اقتباس فقرة>   

وعن طريق هذه العملية، فإنه يتم تحديد ما إذا كان المعامل الثاني يمكن تحويلها لتتناسب مع المعامل الثالث، وعما إذا كانت المعامل الثالث يمكن تحويلها لتتناسب مع المعامل الثاني. إذا يمكن تحويلها حد سواء، أو واحدة يمكن تحويلها ولكن تحويل غامض، وسوء تشكيلها البرنامج.


والفقرات شرح كيف يتم تحويل Foo لint:

و5.16/3 حول condition ? E1 : E2:

<اقتباس فقرة>   

وإلا، إذا كان المعامل الثاني والثالث لديها أنواع مختلفة، وإما تمت (ربما-السيرة الذاتية المؤهلات) نوع فئة، تم إجراء محاولة لتحويل كل من تلك المعاملات إلى نوع من جهة أخرى. [...] E1 يمكن تحويلها إلى تطابق E2 E1 إذا يمكن تحويلها ضمنيا إلى نوع هذا التعبير E2 سيحصلون عليه لو تم تحويلها E2 إلى rvalue (أو نوع كان لديه، إذا E2 هو rvalue).

و4.3 عن "تحويلها ضمنيا":

<اقتباس فقرة>   

وتعبير البريد يمكن تحويلها ضمنيا إلى T نوع إذا وفقط إذا تم بشكل جيد للT t = e; الإعلان، لبعض اخترع متغير ر مؤقت.

و8.5/14 عن نسخة التهيئة (T t = e;)

<اقتباس فقرة>   

وإذا كان نوع المصدر هو (ربما-السيرة الذاتية المؤهلات) نوع الطبقة، وتعتبر وظائف التحويل. وترد وظائف التحويل المطبقة (13.3.1.5)، ويتم اختيار أفضل واحد من خلال قرار الزائد (13.3). تحويل المعرفة من قبل المستخدم المحدد لذلك يطلق لتحويل التعبير مهيئ إلى الكائن الذي يتم تهيئة. إذا كان التحويل لا يمكن أن يتم أو غير واضحة، وسوء تشكيلها التهيئة.

و13.3.1.5 عن المرشحين وظيفة تحويل

<اقتباس فقرة>   

وتعتبر وظائف تحويل S والطبقات قاعدته. تلك التي لا مخبأة داخل S والعائد نوع T أو النوع الذي يمكن تحويله إلى نوع T عبر سلسلة تحويل القياسية (13.3.3.1.1) هي وظائف مرشح.

نصائح أخرى

هذا هو مغطى بشكل إيجابي مربكة من التفصيل في القسم 5.16 القياسية.الجزء المهم في الفقرة 3."إذا E2 هو lvalue:E1 يمكن تحويلها إلى المباراة E2 إذا E1 يمكن أن يكون ضمنيا تحويل (بند 4) نوع 'إشارة إلى T2' ، رهنا القيد في تحويل المرجعية يجب ربط مباشرة (8.5.3) إلى E1."

في التعبير فقط lvalue هو item, لذا فإن السؤال هو ما إذا كان 0 (int) يمكن أن يكون ضمنيا تحويلها إلى نوع Foo.في هذه الحالة لا يوجد التحويل الضمني من أي نوع آخر إلى Foo, منذ متاح فقط وظيفة التحويل يتم وضع علامة explicit.ولذلك لم ينجح, ونحن نتابع مع "إذا E2 هو rvalue ، أو إذا كان التحويل أعلاه لا يمكن القيام به:" (تخطي الجزء إذا كان كلاهما من الطبقة) "خلاف ذلك (أي إذا E1 or E2 لديه nonclass نوع ، أو إذا كان كلاهما من الدرجة أنواع ولكن الأساسية الطبقات ليست إما نفس أو واحدة قاعدة الطبقة الأخرى):E1 يمكن تحويلها إلى المباراة E1 إذا E1 يمكن أن يكون ضمنيا تحويلها إلى نوع هذا التعبير E2 لو E2 تم تحويلها إلى rvalue (أو نوع له ، إذا E2 هو rvalue)."

لذلك نرى أن 0 هو rvalue من نوع int.يمكننا تحويل Foo, بما أننا يمكن تحويل ضمنيا Foo إلى double و من ثم إلى int.ثم:

"باستخدام هذه العملية ، يتم تحديد ما إذا كان المعامل الثاني يمكن تحويلها إلى المباراة الثالثة المعامل ، سواء الثالثة المعامل يمكن تحويلها إلى المباراة المعامل الثاني.إذا كان كل من يمكن تحويلها ، األرضية واحدة يمكن تحويلها ولكن التحويل غامضة ، البرنامج هو سوء تشكيلها.إذا لا يمكن تحويل المعاملات هي دون تغيير و كذلك فحص يتم تنفيذ كما هو موضح أدناه.إذا واحد بالضبط التحويل من الممكن أن التحويل يتم تطبيقها على اختيار المعامل و تحويل المعامل المستخدمة في المكان الأصلي المعامل للفترة المتبقية من هذا القسم."

وبما أننا يمكن تحويل Foo إلى int, نحن تحويل Foo إلى int للفترة المتبقية من العزم.لقد وصلنا الآن إلى اثنين ints كما أنواع التعبير واحد على الأقل هو rvalue.

يمكنني أن أذهب مع الفقرة 5 و 6 ، ولكن أعتقد أنه من الواضح جدا أن التعبير نوع int.

أعتقد أن الوجبات السريعة هي:

  1. مترجم يعمل وفقا لمعيار.

  2. القواعد على نوع من التعبير الشرطي معقدة بسهولة المستفادة.لا دفع المغلف ، لأنك سوف تجعل من الخطأ في وقت ما.(إضافة إلى أن هذا هو بالضبط نوع من المكان الذي مترجم قد تفشل في تنفيذ هذا المعيار على وجه التحديد.)

  3. محاولة تحديد أنواع بحيث كل من الثاني والثالث التعبير هي من نفس النوع.في أي حال, في محاولة لتجنب التعبيرات التي ليست من النوع المطلوب.

نوع من الثلاثي التعبير يتحدد في تجميع الوقت ؛ لا يهم ما some_condition في وقت التشغيل.

أعتقد أن السؤال هو ثم:لماذا مترجم اختيار الباحث بدلا من ضعف في أول سبيل المثال ؟

ومشغل الثلاثي التخمينات نوع من حججها. فإنه لا يمكن تحويل البند إلى int ولكن يمكن تحويل المادة إلى مضاعفة التي ثم يحول إلى كثافة العمليات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top