Могу ли я заставить троичного оператора относиться к моему классу как к булу? - PullRequest
2 голосов
/ 20 августа 2010

Недавно я провел огромный рефакторинг, в котором я изменял большую часть своего кода, чтобы он возвращал логические значения вместо явного кода возврата.Чтобы помочь этому рефакторингу, я решил опираться на компилятор, где это возможно, чтобы он сообщал мне места, где мой код нужно было изменить.Я сделал это, введя следующий класс ( см. Здесь о том, как это работает): :

///
/// 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 );

Если бы я мог«решить» эту проблему, чтобы я мог беспрепятственно использовать свой класс, и, вероятно, продолжал бы использовать его в кодовой базе.Кто-нибудь знает решение этой проблемы?Или просто невозможно делать то, что я хочу?

Ответы [ 6 ]

2 голосов
/ 20 августа 2010

В контексте условного оператора тип выражения представляет собой общий тип из последних двух операндов. Полные правила для определения этого общего типа немного сложны, но ваш случай оказывается тривиальным: если одно из двух возможных возвращаемых значений является типом класса, другое значение должно иметь тот же класс, и общий тип также очевидно учебный класс.

Это означает, что если один из операндов является TypesafeBool, то должен быть и другой.

Теперь проблема, которую вы действительно пытаетесь решить, была решена раньше. Уловка не обеспечивает класс; вместо этого используйте typedef. Например, safe bool .

1 голос
/ 20 августа 2010
      class CCastableToBool
      {  
      public:
         // ...
         operator bool() const
         {  
           //...
           {
              return true;
           } 
           //...
           return false;
         }  
      private:
         // ...
      }; 

но будьте осторожны, в C ++ считается действительно опасным иметь класс, который можно привести к типу bool.Вы предупреждены: -)

вы можете прочитать это там, SafeBool

Вы должны явно вызывать TypesafeBool :: True () во всех ваших троичных тестах.

TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );
1 голос
/ 20 августа 2010

Я не знаю о плавности, у троичного оператора есть некоторые ограничения на его использование ...

Однако, почему вы не определяете две константы?

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

А потом:

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

Конечно, это немного неортодоксально, поскольку я играю с заглавными буквами, чтобы избежать повторного использования зарезервированного слова:)

0 голосов
/ 10 февраля 2011

Хорошая попытка, но если ваша база кода велика, вам, вероятно, лучше использовать статическую проверку, такую ​​как PC-Lint, для поиска неявных преобразований bool <-> int.

0 голосов
/ 20 августа 2010

Не могли бы вы использовать оператор присваивания, который принимает в качестве внешнего аргумента значение bool, а также оператор, который принимает TypesafeBool? Это может быть что-то, чтобы попробовать ...

0 голосов
/ 20 августа 2010

Можно ли сделать конструктор TypesafeBool явным?Конечно, теперь использование должно быть

TypesafeBool result( 1 == 2 ? b : false );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...