2013-09-18 4 views
1

Интерфейс моего класса включает в себя доступ к объекту, который может не существовать. В настоящее время он возвращает указатель, который может быть нулевым. Я хотел бы заменить указатель на std::optional, как предложено here. У аксессуара есть перегрузка const, которая использует Meyers' const_cast trick, чтобы избежать повторения одного и того же кода дважды.Эквивалент const_cast для std :: optional

Короче говоря, я хочу, чтобы заменить это:

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; 
} 

Замена кажется неудовлетворительным, потому что:

  1. он вводит ветвь;
  2. дополнительная сложность несколько поражает цель сделать перегрузку легкой (и тривиально оптимизированной компилятором).

Я предполагаю, что std::optional специализации для справки можно в основном сводится к немного больше, чем указатель с дополнительной безопасностью и интересно, поэтому, если есть какой-то способ, чтобы сохранить простоту решения указателя. Есть ли более удовлетворительный способ написать перегрузку доступа, чтобы использовать std::optional?

+2

Вы уверены, что можете напрямую использовать ссылки на 'std :: optional'? Чтение n3690, это звучит для меня так, как будто требуется * тип объекта *, например указатель или 'std :: reference_wrapper'. – dyp

+0

Есть ли еще компилятор, который поддерживает 'std :: optional'? – us2012

+2

Вам не разрешено создавать экземпляр std :: optional по ссылке (люди, сделавшие это предложение, считают, что это будет слишком противоречиво и, возможно, не обязательно добавляться к C++ 1y). С n3690 (C++ 1y CD) 20.6.2p1: «Программа, которая требует создания шаблона, необязательного для ссылочного типа, или для (возможно, cv-квалифицированных) типов in_place_t или nullopt_t, плохо сформирована». – Nevin

ответ

2

Как упоминалось другими, экземпляр std::optional с ссылочным типом плохо сформирован в стандарте C++ 14. (См. N3690 20.6.2.) Таким образом, использование std::optional в качестве замены замены для указателя (которое указывает на один объект, отсутствие которого представлено значением nullptr), не является жизнеспособным, если вы не желаете копировать объект по значению , а не ссылкой.

Однако спецификация оставляет дверь открытой для добавления таких функций в будущем. Кроме того, section 7.15 из N3672 предлагает обходное решение с использованием std::reference_wrapper.

Обновление: Кроме того, @HowardHinnant сообщает мне, что включение в стандарт было полностью исключено из C++ 14.

Смежные вопросы