Вы можете определить boost::assertion_failed(...)
и BOOST_ENABLE_ASSERT_HANDLER
, чтобы выдать исключение из boost::optional
.
Код:
#include<boost/exception/to_string.hpp>
namespace boost{
void assertion_failed(char const* expr, char const* function, char const* file, long line){
throw std::runtime_error(std::string()
+ expr +
" from " + function +
" at " + file + ":" + boost::to_string(line)
);
}
}
#define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/optional.hpp>
#undef BOOST_ENABLE_ASSERT_HANDLER
int main(){
double d = *boost::optional<double>{}; // throws! (width fairly useful msg)
(void)d;
}
Сообщение об ошибке (если исключение не перехвачено) будет выглядеть примерно так:
terminate called after throwing an instance of 'std::runtime_error'
what(): this->is_initialized() from reference_type boost::optional<double>::get() [T = double] at /usr/include/boost/optional/optional.hpp:992
Другие ссылки: http://boost.2283326.n4.nabble.com/optional-How-to-make-boost-optional-throw-if-trying-to-access-uninitialized-value-td2591333.html
Примечания:
1) Для общего использования может потребоваться точное определение assertion_failed
. Если вы хотите выдать исключение другого рода, я не знаю другого способа, кроме условного выражения в функции assertion_failed
(на мой вкус это слишком глупо):
namespace boost{
void assertion_failed(char const* expr, char const* function, char const* file, long line){
if(std::string("this->is_initialized()") == expr) throw std::domain_error("optional is not intialized");
throw std::runtime_error(std::string()
+ expr +
" from " + function +
" at " + file + ":" + boost::to_string(line)
);
}
}
2) Я не согласен с другим ответом, я думаю, что нужно уметь выбирать поведение. А застревать с assert
не очень хороший вариант. На мой взгляд, в контексте не используется возврат функций. boost::optional
.
3) Теперь существует версия std::experimental::optional
. Любопытно, что они решили быть неосмотрительными к этой проблеме, принимая значение с *
(поскольку возвращается значение unchecked , что согласуется с отсутствием необработанного указателя) .value()
участник может выдать исключение std::experimental::bad_optional_access
. Это интересный выбор дизайна (плюс ни один из двух способов assert
s! Который я считаю правильным.).