Я видел этот хороший код . И хочу использовать его для моего случая.
Для этого я изменил направление, так что combine(f,g,h)(x)
означает: do h(g(f(x)))
.
Но на самом деле я хочу:
до f(x)
.
Если есть результат y
, тогда выполните g(y)
, в противном случае выполните g()
.
Если есть результат z
, тогда выполните h(z)
, в противном случае сделайте h()
.
Итак, вот измененный код:
template<typename ... Fs>
struct combine_impl
{
combine_impl(Fs&& ... fs) : functionTuple(std::forward<Fs>(fs) ...) {}
static constexpr numberOfFs = sizeof ... (Fs);
template<size_t N, typename ... Ts>
auto apply(std::integral_constant<size_t, N>, Ts&& ... ts) const
{
return apply( std::integral_constant<size_t, N + 1>{}
, std::get<N>(functionTuple)(std::forward<Ts>(ts)...));
}
template<typename ... Ts>
auto apply(std::integral_constant<size_t, numberOfFs -1>, Ts&& ... ts) const
{
return std::get<numberOfFs -1>(functionTuple)(std::forward<Ts>(ts)...);
}
template<typename ... Ts>
auto operator()(Ts&& ... ts) const
{
return apply(std::integral_constant<size_t,0>{}, std::forward<Ts>(ts) ...);
}
std::tuple<Fs ...> functionTuple;
};
template<typename ... Fs>
auto combine(Fs&& ... fs)
{
return combine_impl<Fs ...>(std::forward<Fs>(fs) ...);
}
Edit:
Чтобы прояснить, что это был за вопрос:
Пример:
struct FunctorA
{
float operator()(int k) const {return k*2.5f;}
};
struct FunctorB
{
float operator()(float k) const {return k*2.5f;}
};
void main()
{
float result = combine(FunctorA(),FunctorB())(4);
}
отлично работает с кодом.
Но я хочу иметь возможность использовать такой код:
struct FunctorA
{
voidoperator()(int k) const
{
// side effects
}
};
struct FunctorB
{
float operator()() const
{
return 42.f;
}
};
void main()
{
float result = combine(FunctorA(),FunctorB())(4);
}
Это не скомпилируется из-за invalid use of void expression
.
Edit:
после некоторого чтения: это должно быть возможно с sfinae.
Выражение
decltype(std::get<N>(functionTuple)(std::forward<Ts>(std::declval<Ts>())...))
имеет тип void, когда мне нужно использовать другую версию apply.