Интерфейс моего класса включает в себя средство доступа к объекту, который может не существовать. В настоящее время он возвращает указатель, который может быть нулевым. Я хотел бы заменить указатель на std::optional
как предложено Вот. Аксессор имеет const
перегрузка, которая использует Хитрость Мейерса чтобы не повторять один и тот же код дважды.
Короче я хочу заменить это:
T const * MyClass::get() const {
/* non-trivial */
}
T * MyClass::get() {
return const_cast<T *>(const_cast<MyClass const *>(this)->get());
}
с этим:
std::optional<T const &> MyClass::get() const {
/* non-trivial */
}
std::optional<T &> MyClass::get() {
auto t = const_cast<MyClass const *>(this)->get();
return t ? std::optional<T &>(const_cast<T &>(* t)) : std::nullopt;
}
Замена кажется неудовлетворительной, потому что:
Я предполагаю, что std::optional
специализация для ссылки может в основном сводиться к немного большему, чем указатель с дополнительной безопасностью, и поэтому задается вопросом, есть ли какой-то способ сохранить простоту решения указателя. Есть ли более удовлетворительный способ написать перегрузку аксессора для использования std::optional
?
Как уже упоминалось, инстанцирование std::optional
со ссылочным типом плохо сформирован в стандарте c ++ 14. (Увидеть N3690 20.6.2.) Таким образом, используя std::optional
в качестве вставной замены для указателя (который указывает на один объект, отсутствие которого представлено значением nullptr
) не является жизнеспособным, если вы не хотите копировать объект по значению, а не по ссылке.
Тем не менее, спецификация оставляет дверь открытой для добавления такой функциональности в будущем. Дополнительно, раздел 7.15 из N3672 предлагает обходной путь, используя std::reference_wrapper
,
ОбновитьКроме того, @HowardHinnant сообщает мне, что включение в стандарт было полностью исключено из c ++ 14.
Других решений пока нет …