如何使用函数获得模板-模板参数推导
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 argument
和could not deduce template argument for 'overloaded function type' from 'overloaded function type'
)上编译。
有人能解释清楚为什么吗?有办法解决这个问题吗?
编辑好的,我理解为什么现在不可能;对于包含变通方法的答案:在实际代码中有很多不同的Func
,比如100,而只有大约6个函数,比如a、B和C…
表单template<class> class Fun
,无论是作为声明还是作为模板模板参数(就像您所做的那样),都是为类模板设计的,而Func
不是。这是一个函数模板。它们的形式为template</*parameters*/> Ret foo(/*parameters*/)
,不允许作为模板模板参数。
一般来说,函数模板不能像类模板那样被操纵。
有一种情况可以省去传递模板参数的需要:
// Deduces that Func<int> is meant
void (*p)(int) = Func;
然后可以将p
传递给A
、B
和C
。
(类似地,如果您有一个函数void f(void(*p)(int));
,那么形式为f(Func)
的调用也可以。)
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 <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的泛型lambda),则A
、B
和C
的定义不需要更改,并且可以在不指定参数类型的情况下调用:
auto Func = [](auto const&)
{
};
A(Func);
B(Func);
C(Func);
实时演示
- 何时应在构造函数参数中使用 const C++?
- 概念可以与模板模板参数一起使用吗?
- 如何在模板参数中使用 std::is_pod?
- 在模板参数中使用 {} 在 type_trait{} 中时,其作用是什么<T>?
- 可变参数模板参数转发使用逗号运算符
- 在模板函数参数中使用 std::bind
- 函数参数中使用的复杂文字'i'
- 设置内核参数时使用CL_INVALID_ARG_SIZE
- 为什么当我尝试将priority_queue与参数一起使用作为指向结构的指针时会弹出错误
- 标准::原子::compare_exchange与两个memory_order参数一起使用的真实示例
- 如何在 C++ 中将 typedef 与类初始值设定项参数一起使用?
- 在命令行参数中使用引号
- 对可变参数模板使用 const 参数
- SFINAE 和模板函数实例化:为什么在启用了 SFINAE 类型的函数参数中使用模板参数时无法推断模板参数?
- 在简单地移动参数时使用函数模板参数的优点
- 如何切片可变参数模板参数并使用它们?
- 我可以将"token pasting operator"与"const"模板参数一起使用吗?
- 哪个强制转换应与模板类参数一起使用,dynamic_cast或reinterpet_cast?
- 在模板参数中使用 ref<>?
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变