为什么 STL 仿函数本身是模板化的,而不是它们的函数调用运算符?
STL 仿函数是这样实现的:
template<class T>
struct less{
bool operator()(T const& lhs, T const& rhs){
return lhs < rhs;
}
};
这使得我们每次创建这样的仿函数时都会提到(可能很长)类型。为什么它们没有像下面所示的那样实现?有什么理由吗?
struct less{
template<class T>
bool operator()(T const& lhs, T const& rhs){
return lhs < rhs;
}
};
这将使它们可用而无需提及(可能很长)类型。
The STL functors are implemented like this:
template<class T>
struct less{
bool operator()(T const& lhs, T const& rhs){
return lhs < rhs;
}
};
This makes us mention the (possibly long) type everytime we create such a functor. Why are they not implemented like shown below? Any reasons?
struct less{
template<class T>
bool operator()(T const& lhs, T const& rhs){
return lhs < rhs;
}
};
That would make them usable without any mentioning of (possibly long) types.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这也使得不可能将它们专门用于用户定义的类型。
它们应该是一个定制点。
总结一下评论中的讨论:
虽然技术上可以像 Xeo 建议的那样做,但语言标准不允许这样做。
如果允许用户专门化模板的各个功能,那么编写工作类模板将非常困难。然而,在某些情况下,将整个类专门用于用户定义的类型可能是个好主意。
因此C++98标准写道(17.4.3.1):
由于没有“另外指定”Xeo 的代码是允许的,所以我们应该理解它是不允许的。也许并不完全明显!或者“模板专业化”仅适用于类。
新的 C++11 标准对此部分进行了扩展,并对其进行了更详细的说明 (17.6.4.2):
It would also make it impossible to specialize them for user defined types.
They are supposed to be a customization point.
To summarize the discussions in the comments:
Although it is technically possible to do like Xeo suggests, the language standard doesn't allow it.
It is very hard to write a working class template if users are allowed to specialize individual functions of the template. In some cases it might however be a good idea to specialize the whole class for a user defined type.
Therefore the C++98 standard writes (17.4.3.1):
As it isn't "otherwise specified" that Xeo's code is allowed, we are to understand that it is not. Perhaps not totally obvious! Or that "template specializations" only apply to classes.
The new C++11 standard has had this part expanded, and spells it out in more detail (17.6.4.2):
也许:
做的事情很奇怪,但重点是
std::less
、std::less
、std::less
unsigned int>
实现不同的数学函数,当传递(转换的结果)某些参数表达式时,这些函数会产生不同的结果。各种算法和其他标准库组件通过指定函子来工作,因此对我来说,有不同的函子来表示这些不同的数学函数,而不仅仅是一个函子上的operator()
的不同重载是有意义的。此外,具有模板
operator()
的仿函数不能是自适应二元谓词,因为它没有参数类型(参数可以具有任何类型)。因此,如果按照您的建议定义了std::less
,那么它就无法参与
中的内容。另外,还有一个高度推测性的说明 -
std::less
可能是在对模板成员函数的支持广泛普及之前设计的,因为 SGI STL 文档中有各种注释说,“如果您的实现不支持会员模板,则此功能不可用”。我想,对于这样一个简单的组件,会有动力去做一些今天有效的事情。一旦它存在,标准化可能会删除它以支持其他东西,但是是否值得破坏现有代码?如果这是一件大事,那么您或标准都可以引入您所描述的flexible_less
函子。最后,为什么
而不是
用户定义类型,两者可能不一样。是的,这是一个不公平的问题,因为我不知道为什么没有两个模板参数版本的
std::less
;-)Maybe:
Odd thing to do, but the point is that
std::less<int>
,std::less<long>
,std::less<unsigned int>
implement different mathematical functions which produce different results when passed (the result of converting) certain argument expressions. Various algorithms and other standard library components work by specifying a functor, so it makes sense to me that there are different functors to represent those different mathematical functions, not just different overloads ofoperator()
on one functor.Furthermore, a functor with a template
operator()
can't be an Adaptable Binary Predicate, since it doesn't have argument types (an argument can have any type). So ifstd::less
were defined as you suggest then it couldn't participate in the stuff in<functional>
.Also on a highly speculative note --
std::less
was probably designed before support for template member functions was at all widespread, since there are various notes in the SGI STL documentation that say, "if your implementation doesn't support member templates then this isn't available". For such a simple component there would, I guess, be an incentive to do something that works today. Once it exists, the standardization could then have removed it in favour of something else, but was it worth disrupting existing code? If it was that big a deal, then either you or the standard could introduce aflexible_less
functor as you describe.Finally, why
rather than
For user-defined types, the two might not be the same. Yes, this is an unfair question, since I don't know why there's no two-template-argument version of
std::less
;-)