Функция преобразования для проверки ошибок считается хорошей?

Я хотел бы иметь простой способ проверки того, что объект действителен. Я думал о простой функции преобразования, что-то вроде этого:

operator bool() const { return is_valid; }

Проверка того, что он будет действительным, будет очень простым сейчас

// is my object invalid?
if (!my_object) std::cerr << "my_object isn't valid" << std::endl;

Это считается хорошей практикой?

Ответ 1

В С++ 03 вам нужно использовать безопасную идиому bool, чтобы избежать злых вещей:

int x = my_object; // this works

В С++ 11 вы можете использовать явное преобразование:

explicit operator bool() const
{
    // verify if valid
    return is_valid;
}

Таким образом, вам нужно быть явным о преобразовании в bool, так что вы больше не можете делать сумасшедшие вещи случайно (на С++ вы всегда можете делать сумасшедшие вещи):

int x = my_object; // does not compile because there no explicit conversion
bool y = bool(my_object); // an explicit conversion does the trick

Это по-прежнему работает как обычно в таких местах, как if и while, для которых требуется логическое выражение, поскольку условие этих операторов контекстуально преобразуется в bool:

// this uses the explicit conversion "implicitly"
if (my_object)
{
    ...
}

Это описано в разделе & sect; 4 [conv]:

Выражение e может быть неявным преобразуется в тип T тогда и только тогда, когда декларация T t=e; хорошо сформирована, для некоторой изобретенной временной переменной T(& Раздел; 8,5). Некоторые языковые конструкции требуют, чтобы выражение преобразуется в булево значение. выражение e, появляющееся в таком контекст называется контекстно преобразованным в bool и хорошо сформирован тогда и только тогда, когда декларация bool t(e); хорошо сформирована, для некоторых изобретенная временная переменная T (& section 8.5). Эффект либо неявное преобразование такое же, как выполнение декларации и инициализации, а затем используя временную переменная в результате преобразования.

(Разница заключается в использовании bool t(e); вместо bool t = e;.)

Местами было это контекстное преобразование в bool:

  • условия операторов if, while и for;
  • операторы логического отрицания !, логическая связь && и логическая дизъюнкция ||;
  • условный оператор ?:;
  • условие static_assert;
  • необязательное постоянное выражение спецификатора исключения noexcept;

Ответ 2

Нет, простой оператор преобразования bool не, так как теперь вы можете совершать плохие сравнения между несвязанными типами. Как правило, да, функция преобразования - все в порядке. Просто используйте правильный (безопасный bool idiom). Я не могу объяснить это лучше, чем данные ссылки.

Ответ 3

Первоначальный вопрос:

Это считается хорошей практикой?

Проблема с безопасным преобразованием bool была очень актуальной на практике, но, к счастью, теперь она была рассмотрена стандартами.

Но суждение, если этот подход подходит, является вопросом дизайна.

Введя такую ​​ "проверку действительности", вы фактически заявляете, что ваши объекты могут находиться в недопустимом состоянии. То есть, говоря в терминах информатики, вы добавили новое отдельное значение в область значений, представленную вашими объектами. Так называемое нижнее значение

Наиболее ярким примером для домена значений с этим свойством является указатель. Указатель может ссылаться на различные ячейки памяти, но также может быть NULL (недействителен).

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

Опыт показывает, что нижние значения, как правило, подвержены ошибкам, легко забываются и, как правило, больше ответственности, чем актива. Если вы можете упорядочить свой код таким образом, чтобы ваши объекты не могли быть недействительными, ваш код становится проще, легче читать, понимать и поддерживать.