Учитывая функцию T f (T arg1, T arg2), можно ли написать функцию T ncall (FnT fn, T arg1, T arg2, T arg3, ...), которая будет вызывать f, как в моем примере выше и вернуть результат?
Все очень близки к обычной реализации. Вот еще более общее решение, чем заданный вопрос. Он принимает такие функции, как T f(T arg1, T arg2)
, а также T1 f(T2 arg1, T3 arg2)
. Также я назвал функцию foldl в честь ее функциональных корней.
#define AUTO_RETURN( EXPR ) -> decltype( EXPR ) \
{ return EXPR; }
template< typename BinaryFunc, typename First, typename Second >
auto foldl( BinaryFunc&& func, First&& first, Second&& second )
AUTO_RETURN( func( std::forward<First>(first), std::forward<Second>(second) ) )
template<typename BinaryFunc,typename First, typename Second, typename... Rest >
auto foldl( BinaryFunc&& func, First&& first, Second&& second, Rest&&... rest )
AUTO_RETURN(
foldl(
std::forward<BinaryFunc>(func),
std::forward<decltype( func(first,second) )>(
func( std::forward<First>(first), std::forward<Second>(second) )),
std::forward<Rest>(rest)... )
)
Пример того, как это решит вашу проблему:
auto path = foldl( &AppendPath, base, toplevel, sub1, filename );
Другой пример, демонстрирующий всю силу фолдла:
struct stream
{
template< typename T >
std::ostream& operator()( std::ostream& out, T&& t ) const
{
out << std::forward<T>(t);
return out;
}
};
struct Foo
{
Foo( void ) = default;
Foo( const Foo& ) = delete;
Foo& operator=( const Foo& ) = delete;
};
std::ostream& operator << ( std::ostream& out, const Foo& )
{
out << "foo";
return out;
}
int main()
{
foldl( stream(), std::cout, 1, ' ', 1.1, ' ', Foo{}, '\n' );
}
См. Вывод / код в действии на ideone .