Я часто заканчиваю тем, что использую троичные, которые выдают исключения, которые могут показаться немного странными, но экономят день в списках инициализации (следовательно, это помогает для написания звуковых конструкторов, следовательно, помогает для RAII, …). Например. если аргумент a
это smart_ptr<>
что мы хотим не nullptr
тогда я мог бы инициировать такой член, как
member(a ? a->get_something() : throw exception())
Я думаю, что это действительный, законный & безопасное использование (скажите мне, если это не так).
Я недавно переключился на повышение :: исключение, и, к сожалению, condition ? ret_value : BOOST_THROW_EXCEPTION(exception())
не компилируется (так как компилятор не может преобразовать typeof(ret_value)
а также void
).
Есть ли обходные пути лучше, чем создание целого нового частного статического метода и if
внутри?
Это совершенно верно для C ++, но многие компиляторы не будут видеть BOOST_THROW_EXCEPTION как выражение броска, а просто как регулярное выражение типа void. Поскольку стандарт требует, чтобы либо выражение типа void было выражением типа throw, либо обе ветви имели тип void, компилятор отклоняет троичное выражение.
Типичный обходной путь заключается в использовании оператора запятой:
condition ? ret_value : (BOOST_THROW_EXCEPTION(exception()), decltype(ret_value){})
Конечно, вы можете заменить часть после запятой любым выражением правильного типа, и вы можете быть уверены, что она не будет использоваться.
Я думаю, что это действительный, законный & безопасное использование (скажите мне, если это не так).
Это не так, имо. Вы не можете и не должны защищаться от каких-либо дурацких аргументов, которые вы можете получить. Потому что, если вы хотите, вы должны проверить все. любой size_t
Аргумент функции должен быть проверен, если он содержит разумное значение. любой char*
нужно будет проверить, если он равен NULL или нет, и если нет, вам придется проверить, если он разделен нулями. Вам придется применять тысячи проверок во всех ваших классах и функциях, чтобы проверять, что вряд ли произойдет, но может произойти в некоторых странных обстоятельствах.
Рассматривать std::strlen
а также std::string::string(char const*)
: оба требуют, чтобы аргумент был ненулевым указателем на символьную строку с нулевым символом в конце. Чеки не применяются, если вы передадите NULL, вы получите UB.
Во многих случаях функции гарантируют возврат ненулевых указателей. Если такой результат передается вашему конструктору (или strlen
(в этом отношении), дополнительная проверка — пустая трата времени и усилий программирования.
Вкратце: не проверяйте нулевые указатели, а просто требуйте ненулевые указатели. Клиенты несут ответственность за передачу правильных аргументов, потому что только клиентский код знает, нужно ли проверять нулевые указатели, и он должен все равно обрабатывать случай нулевых указателей, проверяя перед вызовом или перехватывая исключение.