C++ 中非模板类的专门成员函数
我试图使用模板化参数专门化非模板类的模板成员函数:
#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 不会被调用。我怎样才能做到这一点?
I'm trying to specialize a template member function of a non-template class using a templatized parameter:
#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
}
I get an error "illegal use of explicit template arguments" with this. What's the right syntax to make this valid?
Update:
Perhaps I've muddled the issue by over-simplifying. What I really want to do is specially handle this one case where there is a dependent name involved, which I think may be what is throwing a monkey wrench into the works here. My original thought was to overload the function as such:
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"!
}
But the special Foo doesn't get called. How can I do that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只有成员函数是模板化的,这意味着您只能在其中使用一个
template<...>
。但这也不能解决问题,因为你不能部分特化一个函数。处理问题的通常方法是通过重载,而不是特化(模板函数的特化没有那么有用)。
请注意,区别在于它们是两个独立的模板函数(而不是专门化)。
编辑:更新后
问题的更新完全改变了问题。您看到的问题是第二个版本的参数是一个从属名称,因此它是不可推论的。给定函数调用,编译器无法确定什么类型 T 和整型常量 N 与该特定实例相匹配。考虑一个不同的示例:
当编译器处理
main
中的调用时,它会实例化模板并提取类型,从中创建一个临时变量,然后尝试决定如何处理foo
但当时它只知道它是用int
右值调用的......原来的inner::type
消失了,现在它只是foo( int() )
并且编译器必须尝试使用所有可能的类型实例化inner_int
以确定它们中的任何一个是否适合,并且在最坏的情况下,如上所述,许多会匹配。Only the member function is templated, which means that you should only use one
template<...>
in there. But that will not solve it either, as you cannot partially specialize a function.The usual way of handling the problem is through overloads, rather than specialization (specialization of template functions is not that useful).
Note that the difference is that they are two separate template functions (rather than an specialization).
EDIT: After the update
The update to the question changes the problem completely. The problem that you are seeing is that the argument of the second version is a dependent name, and as such it is non deducible. Given the function call the compiler is not able to determine what type T, and integral constant N are to match that particular instantiation. Consider a different example:
When the compiler processes the call in
main
, it instantiates the template and extracts the type, from that it creates a temporary, and then it tries to decide what to do withfoo
but at that time it only knows that it is being called with anint
rvalue... the originalinner<double>::type
is gone, now it is justfoo( int() )
and the compiler would have to try and instantiateinner_int
with all possible types to determine whether any of them fits, and in the worse case, as above, many would match.部分函数模板特化是非法的。来自 C++03 标准,§14/2:
您只需重载您的函数:
编辑(响应OP的编辑):
如果您只是在寻找针对此特定场景的解决方法,因为
std(::tr1)::array::iterator
只是T*
,您的“特殊”重载可以是:Partial function template specialization is illegal. From the C++03 standard, §14/2:
You'll want to simply overload your function instead:
EDIT (in response to the OP's edit):
If you're only looking for a workaround for this specific scenario, since
std(::tr1)::array<T,N>::iterator
is simplyT*
, your 'special' overload can be: