У меня есть функция, которая step(f)
:Возвращает результат `f`, если` f` имеет не возвращаемый тип возврата - как реорганизовать этот шаблон?
Выполняет код перед вызовом
f
.Звонки
f()
.Выполняет код после вызова
f
.Возвращает
f
«ы значение результата еслиf
не возвращаетvoid
.
Небольшой кусок кода, реализующего step
беспокоит меня больше, чем это необходимо, так как в четвертой точке, описанной выше:
template <typename TF>
auto step(TF&& f)
{
// Execute some actions before `f`.
do_something();
using f_return_type = decltype(f());
return static_if(std::is_same<f_return_type, void>{})
.then([](auto&& xf) mutable
{
// Do not return anything if `xf` returns void.
xf();
// Execute some actions after `f`.
do_something_after_f();
})
.else_([](auto&& xf) mutable
{
auto result = xf();
// Execute some actions after `f`.
do_something_after_f();
return result;
})(std::forward<TF>(f));
}
(Обратите внимание на повторение вызова f
и do_something_after_f
.)
Мне нужно использовать какое-то условное время компиляции (либо специализация шаблона, либо static_if
, как показано на рисунке пример) к ответвлению в зависимости от типа возврата f
.
В идеале, я хотел бы, чтобы компилировать:
template <typename TF>
auto step(TF&& f)
{
// Execute some actions before `f`.
do_something();
decltype(auto) eventual_result = f();
// Execute some actions after `f`.
do_something_after_f();
return result;
}
Но это не так, потому что eventual_result
может быть void
, который неполный тип.
Есть ли способ рефакторинга этого кода, чтобы избежать повторения при звонке f()
и do_something_after_f()
?
Вы ищете 'optional'? Я не могу сказать из вопроса, почему вам нужно что-то вернуть, если вы просто отбросите его. –
@sleeptightpupper. Основная проблема заключается в том, что мы хотим, чтобы функция возвращала любые значения 'f', но поскольку после вызова' f' есть код, его значение должно быть сохранено. Однако вы не можете сохранить значение 'void', что означает, что вам нужны две версии: одна для' f' с возвращаемым типом 'void' и другая для других типов возврата. – chris
Я мог видеть что-то работающее, если вы абстрагируетесь, имея две версии в виде 'void foo (...) {/ * before */return callAndThen (f, [&] {/ * после * /});' – chris