Неоднозначность перегрузки с помощью boost:: optional, обходной путь?

Я хотел бы перегрузить с помощью boost:: optional, но не могу из-за двусмысленности перегрузки и ищу обходной путь.

Например, следующий код не скомпилируется из-за неоднозначности:

void foo() { ... }
void foo(const Class& A) { ... }
// \deprecated
void foo(boost::optional<const Class&> A) { A ? foo(A) : foo() }

Причина, по которой я хочу сделать эту странную вещь, заключается в том, что из-за ошибок, возникших из-за проблем с rvalue/lvalue с boost::Optional, вместо этого я заменяю экземпляры boost::Optional перегрузками функций. Проблема в том, что происходят некоторые поломки API, поэтому мне нужно оставить старые определения функций устаревшими.

Пример поломки API с другими параметрами по умолчанию,

void foo(int a=0, boost::optional<Bar> A=boost::none, float b=0.0) { ... }

требует от меня изменить порядок аргументов:

void foo(int a=0, float b=0.0) { ... }
void foo(Bar A, int a=0, float b=0.0) { ... }

но теперь случай, который ломается, - это foo(1, boost::none, 3.14);, поэтому я хочу сохранить устаревшее определение функции только для этого типа вызова функции. Есть ли элегантный обходной путь?

Я полагаю, что одна (уродливая) возможность

// \deprecated
void foo(int a, boost::optional<DummyClass> A, float b=0.0) { ... }

но это не вызывает радости. Любые идеи?


person gchen    schedule 28.10.2019    source источник
comment
Почему не void foo(boost::optional<const Class&> A) { A ? foo(*A) : foo() }? Во-вторых, foo(int a=0, boost::optional<Bar> A, float b=0.0) не является допустимым C++, у вас не может быть аргумента, отличного от значения по умолчанию, после аргумента по умолчанию.   -  person Yakk - Adam Nevraumont    schedule 28.10.2019
comment
относительно второго комментария Адама, да, моя ошибка, соответственно отредактировал вопрос; @ Jarod42, извините, я не знаком с устаревшим требованием или =delete, не могли бы вы уточнить или предоставить ресурс для справки?   -  person gchen    schedule 28.10.2019
comment
Нет, я имел в виду, действительно ли вам нужна устаревшая функция, или достаточно пометить ее как удаленную, чтобы запретить ее использование (void foo(boost::optional<const Class&> A) = delete;).   -  person Jarod42    schedule 28.10.2019
comment
@ Jarod42 Jarod42 О, я вижу - к сожалению, существующий код уже передает аргумент boost::none, поэтому удаление функции нарушит код других людей:/   -  person gchen    schedule 28.10.2019


Ответы (1)


Как указано в комментарии, в вашем обычном случае есть опечатка, которая делает рекурсивный вызов. Исправленная версия:

void foo() { /*...*/ }
void foo(const Class& A) { /*...*/ }

[[deprecated]] void foo(boost::optional<const Class&> A) { A ? foo(*A) : foo(); }

Вместо этого я заменяю экземпляры boost::optional перегруженными функциями.

Таким образом, вы можете заменить:

void foo(int a=0, boost::optional<Bar> A=boost::none, float b=0.0) { /*...*/ }

By

void foo(int a = 0) {/*..*/}
void foo(int a, Bar, float b = 0.0f) { /*..*/ }
void foo(int a, boost::none_t, float b = 0.0f) { /*..*/ }

[[deprecated]] void foo(int a, boost::optional<Bar>, float b = 0.0f);
person Jarod42    schedule 28.10.2019