2 ответа
Если вы хотите иметь возможность пропустить параметры в вызове и делать такие вещи, как:
create_child();
create_child(std::make_optional(int_param));
create_child(std::make_optional(float_param),
(... ? std::optional<int>{} : int_param);
Вы можете использовать некоторые шаблоны и рекурсивную функцию. Следующий код является примером. Есть способы сделать это лучше, например, создать только один child
и не возвращать пакет, или использовать идеальную пересылку.
//Recursion base case
//Recieves values to pass to child in a tuple
//Returns created child
template <typename... Ts>
child create_child_detail(std::tuple<Ts...> t)
{
//Is there a better way to apply a tuple to a ctor?
return std::apply([](Ts... ts){ return child(ts...); }, t);
}
//Recursive function
//Removes arguments from variadic template and adds arguments to tuple
template <typename... Ts, typename O, typename... Os>
child create_child_detail(std::tuple<Ts...> t, std::optional<O> o, std::optional<Os>... os)
{
if (o) //Valid optional, add value to tuple to send to child
return create_child_detail(std::tuple_cat(t, std::make_tuple(*o)), os...);
else //Invalid optional, value should not be added to child
return create_child_detail(t, os...);
}
//Called by user
//Just calls create_child_detail
template <typename... Ts>
child create_child(std::optional<Ts>... ts)
{
return create_child_detail(std::tuple<>{}, ts...);
}
Пустые опции удаляются. Аргументы передаются child
в том порядке, в котором вы их написали. Это может принимать любое количество аргументов. Я тестировал его на Coliru здесь, чтобы вы могли поиграть с ним.
Используйте функцию для создания child
объектов, которые содержат ветви. Передайте std::optional
в качестве параметров:
child make_child(const std::optional<int>& int_param,
const std::optional<float>& float_param)
{
if (int_param && float_param) {
return child(std::to_string(int_param.value()),
std::to_string(float_param.value()));
}
// Rest of the branches ...
}
Это позволяет вам создать объект child
следующим образом:
child c = make_child(... ? std::optional<int>() : int_param,
... ? std::optional<float>() : float_param);