هل يمكنني جعل المشغل الثلاثية يعامل صفي مثل المنسال؟

StackOverflow https://stackoverflow.com/questions/3529449

سؤال

لقد قمت مؤخرًا بإعادة تمهيد كبير حيث كنت أغير الكثير من الكود لإرجاع Booleans بدلاً من رمز الإرجاع الصريح. للمساعدة في هذه إعادة الطعن ، قررت أن أميل إلى المترجم حيثما أمكن ذلك من خلال الحصول عليه لأخبرني بالأماكن التي يجب تغيير الكود الخاص بي. فعلت هذا من خلال تقديم الفصل التالي (انظر هنا للحصول على lowdown حول كيفية عمل هذا):

///
/// Typesafe boolean class
///
class TypesafeBool
{
private:
    bool m_bValue;
    struct Bool_ { 
        int m_nValue; 
    };
    typedef int Bool_::* bool_;
    inline bool_ True() const { return &Bool_::m_nValue; }
    inline bool_ False() const { return 0; }

public:
    TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
    operator bool_() const { return m_bValue ? True() : False(); }
};

الآن ، بدلاً من استخدام عادي bool اكتب كنوع الإرجاع ، لقد استخدمت هذا الفصل مما يعني أنه لا يمكنني تجميع شيء من هذا القبيل بعد الآن:

TypesafeBool SomeFunction();
long result = SomeFunction(); // error

عظيم: لقد جعل إعادة الإدارة قابلة للإدارة على قاعدة كود ضخمة من خلال السماح للمترجم بعمل الكثير من العمل الشاق بالنسبة لي. لذا ، فقد انتهيت الآن من إعادة تهيئتي وأود تمامًا الحفاظ على هذا الفصل معلقًا والاستمرار في استخدامه لأنه يمنحنا مستوى إضافيًا من الأمان bool النوع لا.

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

TypesafeBool result = ( 1 == 2 ? SomeFunction() : false ); // error: different types used
TypesafeBool result = ( 1 == 2 ? SomeFunction() : (TypesafeBool)false );

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

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

المحلول

      class CCastableToBool
      {  
      public:
         // ...
         operator bool() const
         {  
           //...
           {
              return true;
           } 
           //...
           return false;
         }  
      private:
         // ...
      }; 

ولكن احذر ، في C ++ ، يعتبر خطيرًا حقًا أن يكون لديك فئة يمكن إلقاؤها إلى Bool. لقد تم تحذيرك :-)

يمكنك قراءة هذا هناك ، آمن

يجب عليك استدعاء Typesafebool :: true () في جميع الاختبارات الثلاثية.

TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );

نصائح أخرى

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

هذا يعني أنه إذا كان أحد المعاملات هو نوع من الأنواع ، فيجب أن يكون الآخر كذلك.

الآن تم حل المشكلة التي تحاول حلها حقًا من قبل. الحيلة لا توفر فصلًا ؛ بدلاً من ذلك ، استخدم typedef. انظر على سبيل المثال منطقي آمن.

لا أعرف عن طريقة سلسة ، فإن المشغل الثلاثية لديه بعض القيود على استخدامه ...

ومع ذلك ، لماذا لا تحدد ثوابت اثنين؟

TypesafeBool const True = TypesafeBool(true);
TypesafeBool const False = TypesafeBool(false);

وثم:

TypesafeBool result = ( 1 == 2 ? SomeFunction() : False );

بالطبع ، إنه أمر غير تقليدي بعض الشيء منذ أن ألعب على الرسملة لتجنب إعادة استخدام كلمة مخصصة :)

هل من المحتمل أن يجعل مُنشئ الأنواع الصافية صريحة؟ بالطبع ، يجب أن يكون الاستخدام الآن

TypesafeBool result( 1 == 2 ? b : false );

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

محاولة لطيفة ، ولكن إذا كانت قاعدة التعليمات البرمجية كبيرة ، فمن المحتمل أن تكون أفضل حالًا باستخدام مدقق ثابت مثل PC-Lint للبحث عن تحويلات منطقية ضمنية <-> int بدلاً من ذلك.

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