我正在尝试使用模板化参数来专门化非模板类的模板成员函数:
#include <array>
class C
{
public:
template<class Container>
void Foo( Container& )
{
// ...
}
};
template<class T, std::size_t N>
template<>
void C::Foo< std::tr1::array<T,N> >( std::tr1::array<T,N>& )
{
// special
}
我收到错误“非法使用显式模板参数”。什么是使这个有效的正确语法?
更新:
也许我过度简化了这个问题。我真正想做的是专门处理这个案例,其中涉及一个从属名称,我认为这可能是什么在这里投入一个猴子扳手。我最初的想法是重载这个功能:
class C
{
public:
template<class Iter>
void Foo( Iter )
{
std::cout << "Normal\n";
}
template<class T, std::size_t N>
void Foo( typename std::tr1::array<T,N>::iterator )
{
std::cout << "Special\n";
}
};
int main()
{
C c;
std::tr1::array<int,10> a1;
c.Foo( a1.begin() ); // Doesn't print "Special"!
}
但特殊的Foo没有被调用。我怎么能这样做?
答案 0 :(得分:2)
只有成员函数是模板化的,这意味着你只应该使用一个template<...>
。但这也无法解决,因为你不能部分专门化一个功能。
处理问题的常用方法是通过重载,而不是专门化(模板函数的专业化没有那么有用)。
struct test {
template <typename Container>
void f( Container& ) { ... }
template <typename T, int N>
void f( std::array<T,N>& ) { ... }
};
请注意,不同之处在于它们是两个独立的模板函数(而非专业化)。
编辑:更新后
问题的更新完全改变了问题。您看到的问题是第二个版本的参数是一个从属名称,因此它是不可推导的。给定函数调用,编译器无法确定什么类型T,并且整数常量N与该特定实例化相匹配。考虑一个不同的例子:
template <typename T>
struct inner_int {
typedef int type;
};
template <typename T>
void foo( typename inner_int<T>::type ) {
}
int main() {
foo( inner_int<double>::type() );
}
当编译器在main
中处理调用时,它实例化模板并从中创建一个临时的类型,然后它尝试决定如何处理foo
但是在那个时间它只知道用int
rvalue调用它...原来的inner<double>::type
已经消失了,现在它只是foo( int() )
而且编译器必须尝试实例化{{ 1}}用所有可能的类型来确定它们是否适合,在更糟糕的情况下,如上所述,很多都匹配。
答案 1 :(得分:1)
部分功能模板专业化是非法的。从C ++ 03标准,§14/ 2:
template-declaration 只能作为命名空间范围或类范围声明出现。在函数模板声明中, declarator-id 应为 template-name (即,不是 template-id )< / strong>即可。 [注意:在类模板声明中,如果类名是 template-id ,则声明声明类模板部分特化。]
您只想简单地重载您的功能:
class C
{
public:
template<typename Container>
void Foo(Container&)
{
// ...
}
template<typename T, std::size_t N>
void Foo(std::tr1::array<T, N>&)
{
// special
}
};
编辑(响应OP的编辑):
如果您只是针对此特定方案寻找解决方法,因为std(::tr1)::array<T,N>::iterator
只是T*
,您的'特殊'重载可以是:
template<typename T>
void Foo(T*&)
{
// special
}