如何在模板参数列表中传递模板函数

37
假设我有一个模板函数:template
template<typename T>
T produce_5_function() { return T(5); }

我该如何将整个模板传递给另一个模板

如果produce_5_function是一个函数对象,那就没有问题了:

template<typename T>
struct produce_5_functor {
  T operator()() const { return T(5); }
};
template<template<typename T>class F>
struct client_template {
  int operator()() const { return F<int>()(); }
};
int five = client_template< produce_5_functor >()();

但我希望能够使用原始函数模板来实现这一点:

template<??? F>
struct client_template {
  int operator()() const { return F<int>(); }
};
int five = client_template< produce_5_function >()();

我怀疑答案是“你无法做到这一点”。
2个回答

24
我猜想答案是“你不能这样做”。是的,确实如此,你不能将函数模板作为模板参数传递。根据14.3.3规定:模板参数必须是类模板或别名模板的名称,并表示为id-expression。在将其传递到其他模板之前,需要实例化模板函数。一种可能的解决方案是传递一个包含静态produce_5_function的类类型,如下所示:
template<typename T>
struct Workaround {
  static T produce_5_functor() { return T(5); }
};
template<template<typename>class F>
struct client_template {
  int operator()() const { return F<int>::produce_5_functor(); }
};
int five = client_template<Workaround>()();

通过使用别名模板,我可以更接近实现目标:

template <typename T>
T produce_5_functor() { return T(5); }

template <typename R>
using prod_func = R();

template<template<typename>class F>
struct client_template {
  int operator()(F<int> f) const { return f(); }
};

int five = client_template<prod_func>()(produce_5_functor);

3
模板模板参数不能是函数模板,这是否有根本原因?这个问题将来可能会得到解决吗? - Olumide
1
@Olumide:可能是因为它增加了很多复杂性,而且很容易解决(请参见mfontanini的答案)。同样适用于部分特化,它比模板模板参数使用得更多。 - Ben Voigt

6
如何对该函数进行封装?
template<typename T>
struct produce_5_function_wrapper {
    T operator()() const { return produce_5_function<T>(); }
};

接下来,您可以使用包装器而非函数:

int five = client_template< produce_5_function_wrapper >()();

仅使用模板函数是不够的,"模板模板函数"这种东西是不存在的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接