Я определяю набор шаблонов функций:
template < typename type >
void foo ( type object )
{
// foo the object
}
template < typename type >
void bar ( type object )
{
// bar the object
}
template < typename type >
void baz ( type object )
{
// baz the object
}
Теперь я хочу определить шаблон функции, который берет указатель на любую из функций из приведенного выше.
template < /* ??? */ , typename T , typename... TT >
void for_each ( T parameter , TT... other parameters )
{
// process the first parameter using the function pointer defined by the first template parameter
// recursice call to for_each
}
Как правильно объявить первый параметр шаблона?
Постскриптум Я знаю, что есть обходной путь, чтобы обернуть первые три функции в классе и сделать их статичными. Я просто хочу знать, есть ли прямой способ решить проблему.
struct foo_overload_set_t {
template<typename... Ts>
auto operator()(Ts&&... ts) const
-> decltype( foo(std::forward<Ts>(ts)...) ) {
return ( foo(std::forward<Ts>(ts)...) );
}
};
static const foo_overload_set_t foo_overload_set;
сейчас foo_overload_set
является единственным объектом, который может рассматриваться как функция, и при вызове выполняет разрешение перегрузки функции foo
основываясь на переданных параметрах.
То есть, foo( a, b, c, d, e )
выполняет тот же код и дает тот же результат, что и foo_overload_set( a, b, c, d, e )
для любого набора аргументов.
Но foo_overload_set
является объектом, в то время как foo
является неопределенным набором функций, созданных на лету на основе параметров, используемых для его вызова.
Мы можем передать указанный объект вашему for_each
:
template<typename OverloadSet>
void for_each( OverloadSet ) {} // do nothing
template < typename OverloadSet , typename T , typename... TT >
void for_each ( OverloadSet overload, T&& parameter , TT&&... other_parameters )
{
overload( std::forward<T>(parameter) );
for_each( overload, std::forward<TT>(other_parameters)... );
}
вызывается как:
for_each( foo_overload_set, a, b, c, d, e );
который продолжает звонить foo
на a
, Затем на b
, Затем на c
, так далее.
Параметры шаблона шаблона могут быть только шаблонами классов, а не шаблонами функций, поэтому вам нужно будет обернуть шаблон функции в шаблон класса:
template<typename T>
struct foo_wrap {
static constexpr void (*fn)(T) = &foo<T>;
};
В C ++ 1y вы можете рассмотреть возможность упорядочения этого с помощью общей лямбды, хотя это будет параметр функции, а не параметр шаблона:
for_each(..., [](auto t) { foo(t); }, ...);
Аргументы шаблона должны быть классами.
#include <iostream>
template <typename... T> void ignore( T... ) {}
template < template < typename T > class f_, typename... args_>
void fun( args_&&... args) {
int dummy[] { ( f_<args_>{}( std::forward<args_>(args) ), 0)...};
ignore(dummy);
}
template < typename T >
struct bar {
void operator()( T v ) const {
std::cout << v << " ";
}
};
int main() {
int a{1}, b{2}, c{3};
float d{4.5};
fun<bar>(a, b, c, d );
}