Здравствуйте, LaptevVV, Вы писали:
LVV>Например: https://cpppatterns.com/patterns/optional-arguments.html
Интересно, у вас специально получилось дать ссылку на крайне спорный паттерн?
This approach is more expressive than using pointers and nullptr.
Если брать пример использования:
foo(5, std::nullopt, std::nullopt);
то это ничем не лучше:
foo(5, nullptr, nullptr);
Выразительнее было бы что-то вроде:
foo(5, no_f_specified, no_b_specified);
Где вместо `no_f_specified` и `no_b_specified` будут вменяемые, привязанные к прикладной области, именованные константы.
Вроде `default_scale` и `no_pretty_printing`:
foo(5, default_scale, no_pretty_printing);
По поводу выразительности самой декларации:
void foo(int i,
std::optional<double> f,
std::optional<bool> b);
Тоже не однозначно, т.к. если придерживаться правила современного С++ о том, что голые указатели только невладеющие, то декларация:
void foo(int i,
const double * f,
const bool * b);
такая же понятная: качестве f и b допускается передача nullptr, если бы не допускалась, то вместо указателя была бы ссылка.
И еще вопрос о том, а что эффективнее -- передавать указатель на опциональный double или же std::optional для double. Ведь в C++ std::optional налагает плату в виде дополнительного bool-а, тем самым увеличивая размер параметра.
Однозначный выигрыш от std::optional есть когда мы передаем опциональный аргумент по значению, а не по ссылке/указателю. Что-то вроде:
struct MyData { ... };
struct ProcessingParams { ... };
void process(MyData what,
// Принимаем по значению.
std::optional<ProcessingParams> how) {...}
std::optional<ProcessingParams> // Возвращаем по значению.
try_find_custom_params() {...}
process(my_data, try_find_custom_params());
Вот в этом случае да, аргумент в виде optional удобнее, нежели указатель.
Но про такой сценарий по ссылке и не сказано