模板函数指针作为模板参数

时间:2014-02-03 09:40:20

标签: c++ templates c++11 function-pointers c++14

我定义了一组函数模板:

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
    }

声明第一个模板参数的正确方法是什么?

P.S。我知道有一种解决方法可以将类中的前三个函数包装在一起并使它们保持静态。我只是想知道是否有解决问题的直接方法。

3 个答案:

答案 0 :(得分:5)

模板模板参数只能是类模板,而不是函数模板,因此您必须将函数模板包装在类模板中:

template<typename T>
struct foo_wrap {
    static constexpr void (*fn)(T) = &foo<T>;
};

在C ++ 1y中,您可以考虑使用通用lambda来简化它,尽管这将是一个函数参数,而不是模板参数:

for_each(..., [](auto t) { foo(t); }, ...);

答案 1 :(得分:1)

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,等等。

答案 2 :(得分:0)

模板模板参数必须是类。

#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 );
}