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

时间:2022-08-14 18:52:46

I define a set of function templates:

我定义了一组函数模板:

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
}

Now I want to define a function template which takes a pointer to any of the functions from the above.

现在我要定义一个函数模板,它接受一个指向上述函数的指针。

    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
    }

What is the correct way to declare the first template parameter?

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

P.S. I do know that there is a workaround to wrap the first three functions each in a class and make them static. I just want to know if there is a straight way to solve the problem.

附注:我知道有一个方法可以将前三个函数分别封装在一个类中并使它们保持静态。我只是想知道是否有直接的方法来解决这个问题。

3 个解决方案

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

now foo_overload_set is a single object which can be treated like a function, and when invoked does overload resolution on the function foo based off the passed in parameters.

现在foo_overload_set是一个可以像函数一样处理的对象,当调用它时,会根据传入的参数对函数foo进行重载解析。

Ie, foo( a, b, c, d, e ) runs the same code and gives the exact same result as foo_overload_set( a, b, c, d, e ) for any set of arguments.

例如,foo(a, b, c, d, e)运行相同的代码,并为任何一组参数提供与foo_overload_set(a, b, c, d, e)相同的结果。

But foo_overload_set is an object, while foo is an indeterminate set of functions created on the fly based off parameters used to call it.

但是foo_overload_set是一个对象,而foo是一组不确定的函数集,这些函数是在运行时根据用于调用它的参数创建的。

We can pass said object to your for_each:

我们可以把这个对象传递给你的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)... );
}

invoked like:

调用:

for_each( foo_overload_set, a, b, c, d, e );

which proceeds to call foo on a, then on b, then on c, etc.

然后在a上调用foo,然后在b上,然后在c上,等等。

#2


5  

Template template parameters can only be class templates, not function templates, so you'd have to wrap the function template in a class template:

模板模板参数只能是类模板,不能是函数模板,所以必须将函数模板包装在类模板中:

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

In C++1y you might consider streamlining this with a generic lambda, although that would be a function parameter, not a template parameter:

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

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

#3


0  

template template arguments have to be classes.

模板参数必须是类。

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

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

now foo_overload_set is a single object which can be treated like a function, and when invoked does overload resolution on the function foo based off the passed in parameters.

现在foo_overload_set是一个可以像函数一样处理的对象,当调用它时,会根据传入的参数对函数foo进行重载解析。

Ie, foo( a, b, c, d, e ) runs the same code and gives the exact same result as foo_overload_set( a, b, c, d, e ) for any set of arguments.

例如,foo(a, b, c, d, e)运行相同的代码,并为任何一组参数提供与foo_overload_set(a, b, c, d, e)相同的结果。

But foo_overload_set is an object, while foo is an indeterminate set of functions created on the fly based off parameters used to call it.

但是foo_overload_set是一个对象,而foo是一组不确定的函数集,这些函数是在运行时根据用于调用它的参数创建的。

We can pass said object to your for_each:

我们可以把这个对象传递给你的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)... );
}

invoked like:

调用:

for_each( foo_overload_set, a, b, c, d, e );

which proceeds to call foo on a, then on b, then on c, etc.

然后在a上调用foo,然后在b上,然后在c上,等等。

#2


5  

Template template parameters can only be class templates, not function templates, so you'd have to wrap the function template in a class template:

模板模板参数只能是类模板,不能是函数模板,所以必须将函数模板包装在类模板中:

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

In C++1y you might consider streamlining this with a generic lambda, although that would be a function parameter, not a template parameter:

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

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

#3


0  

template template arguments have to be classes.

模板参数必须是类。

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