【问题标题】:Template function pointer as a template parameter模板函数指针作为模板参数
【发布时间】:2014-02-03 09:40:20
【问题描述】:

我定义了一组函数模板:

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
    }

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

附注我确实知道有一种解决方法可以将前三个函数分别包装在一个类中并使它们成为静态的。我只是想知道是否有直接的方法可以解决问题。

【问题讨论】:

  • 如果你不关心for_each()里面的type,那么很简单,template&lt;typename F, typename... TT&gt; void for_each(F f, TT... other)
  • @Kolyunya 你能在问题中添加一个假设用例吗?
  • @galop1n 用例在问题中明确定义 - 处理异构可变参数包。
  • @Kolyunya 您正在尝试将其编译为 C。

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


【解决方案1】:

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

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

在 C++1y 中,您可能会考虑使用通用 lambda 对其进行简化,尽管这将是一个函数参数,而不是模板参数:

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

【讨论】:

    【解决方案2】:
    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 );
    

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

    【讨论】:

      【解决方案3】:

      模板模板参数必须是类。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-10
        • 1970-01-01
        • 2019-04-13
        • 1970-01-01
        • 2015-06-29
        • 2015-09-10
        相关资源
        最近更新 更多