繁体   English   中英

如何使用函数获取模板模板参数推导?

[英]How to get template template argument deduction working with functions?

考虑一组函数,如

template< class Fun >
void A( const Fun& )
{
}

template< class Fun >
void B( const Fun& )
{
}

template< class Fun >
void C( const Fun& )
{
}

旨在将函数类型作为参数。 然后,这是完全可以的:

template< class T >
void Func( const T& )
{
}

A( Func< int > );
B( Func< int > );
C( Func< int > );

现在,我想摆脱重复的int temaplate参数,所以我尝试这样做:

template< class T >
struct Helper
{
  template< template< class > class Fun >
  static void A( Fun< T >& f )
  {
    A( f );
  }

  template< template< class > class Fun >
  static void B( Fun< T >& f )
  {
    B( f );
  }

  ...
};

typedef Helper< int > IntHelper;
IntHelper::A( Func );  //error
IntHelper::B( Func );  //
IntHelper::C( Func );  //

但是这无法在gcc 4.5.1上编译( 'error: no matching function for call to 'Helper<int>::A(<unresolved overloaded function type>)' )和MSVC10( cannot use function template 'void Func(const T &)' as a function argumentcould not deduce template argument for 'overloaded function type' from 'overloaded function type'

有人可以解释为什么,并且有解决方法吗?

编辑确定我明白为什么现在不可能; 对于包含解决方法的答案:在实际代码中有很多不同的Func ,比如100,而只有大约6个函数,如A,B和C ......

Func是一个函数模板,因此您无法将其作为值传递给函数。

您也无法将其作为模板模板参数传递,因为模板模板参数必须是类模板(而不是函数模板)。

可以传递包装函数模板的模板模板参数(例如,从静态成员函数返回其实例化):

template<class T> struct FuncHelper {
    static void (*f())(const T &) { return &(Func<T>); }
};
template<typename T>
struct Helper
{
  template< template< class > class Fun >
  static void A()
  {
    A( Fun<T>::f() );
  }
};
Helper<int>::A<FuncHelper>();

表单template<class> class Fun ,无论是作为声明还是作为模板模板参数(就像您所拥有的那样),仅针对模板而设计,而Func则不是。 这是一个功能模板。 那些具有表单template</*parameters*/> Ret foo(/*parameters*/) ,并且不允许它们作为模板模板参数。

一般来说,函数模板不能像类模板那样进行操作。

有一种情况可以避免传递模板参数:

// Deduces that Func<int> is meant
void (*p)(int) = Func;

然后你可以将p传递给ABC

(类似地,如果你有一个函数void f(void(*p)(int));那么调用f(Func)形式就好了。)

虽然可以使用类模板作为模板参数,例如

template <typename> class Foo;

template <template <typename> class C> void doit() { /* ...*/ };

doit<Foo>();

它(语义上)不可能使用函数模板作为模板参数(没有“函数模板指针”)。 通常的方法是使用函数对象,例如

template <typename T>
struct Func
{
  void operator()(T const &) const
  {
     /* ... */
  }
};


template <typename T>
struct helper
{
  template <template <typename> class F>
  static void A()
  {
    A(F<T>);
  }
  // etc
};

typedef helper<int> int_helper;

int_helper::A<Func>();

如果Func可以声明为带有auto类型参数的lambda(使用C ++ 14的通用lambdas ),那么ABC的定义不需要更改,并且可以在不必指定参数类型的情况下调用:

auto Func = [](auto const&)
{
};

A(Func);
B(Func);
C(Func);

现场演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM