考虑一组功能,如
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
s,比如100,而只有大约6个函数,如A,B和C ......
答案 0 :(得分:3)
Func
是一个函数模板,因此您无法将其作为值传递给函数。
您也无法将其作为template template parameter传递,因为模板模板参数必须是类模板(而不是函数模板)。
您可以传递包装函数模板的模板模板参数(例如,从静态成员函数返回其实例化):
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>();
答案 1 :(得分:3)
表单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)
形式就可以了。)
答案 2 :(得分:3)
虽然可以使用类模板作为模板参数,例如
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>();
答案 3 :(得分:1)
如果Func
可以声明为带有auto
类型参数的lambda(使用C++14's generic lambdas),那么A
,B
的定义和C
不需要更改,无需指定参数类型即可调用:
auto Func = [](auto const&)
{
};
A(Func);
B(Func);
C(Func);