[英]Specialization of 'template<class _Tp> struct std::less' in different namespace
我专门针对数据类型使用“较少”(谓词)。
代码如下所示:
template<>
struct std::less<DateTimeKey>
{
bool operator()(const DateTimeKey& k1, const DateTimeKey& k2) const
{
// Some code ...
}
}
编译时(在 Ubuntu 9.10 上为 g++ 4.4.1),出现错误:
不同命名空间中“模板结构 std::less”的专业化
我做了一些研究,发现有一个“解决方法”,它涉及将专业化包装在 std 命名空间中 - 即将代码更改为:
namespace std {
template<>
struct less<DateTimeKey>
{
bool operator()(const DateTimeKey& k1, const DateTimeKey& k2) const
{
// Some code ...
}
}
}
这确实关闭了编译器。 然而,这个解决方案来自一个 5 岁的孩子(“伟大的”维克多·巴扎罗夫(Victor Bazarof)同样[双关语意外])。 此修复程序是否仍然可行,或者是否有更好的方法来解决此问题,或者“旧方法”仍然有效?
这仍然是这样做的方法。 不幸的是,您不能像在类中那样在名称空间中声明或定义函数:您需要将它们实际包装在名称空间块中。
如果您需要专门化标准算法,您可以在 std 命名空间中进行。 根据标准,这是唯一允许您在该命名空间内执行的操作。
[lib.reserved.names]/1
除非另有说明,否则 C++ 程序向命名空间 std 或命名空间 std 内的命名空间添加声明或定义是未定义的。 程序可以将任何标准库模板的模板特化添加到命名空间 std。 标准库模板的这种特化(完全或部分)会导致未定义的行为,除非声明依赖于用户定义的外部链接名称,并且除非特化满足原始模板的标准库要求
现在,问题是您是否真的想要专门化std::less
。 请注意, std::less
将调用为您的类型定义的比较运算符,因此您可以提供该操作而不是专门化模板。
为您的特定类型专门化std::less
的问题是,如果您提供的操作与operator<
为您的类型执行的operator<
不同,则会引起混淆。 如果它们执行相同的操作,只需保留默认的std::less
定义而无需专门化。
如果您不想提供比较运算符,但仍想在关联容器或需要比较器的算法中使用该类型,则可以使用其他名称提供外部比较函子,以免混淆其他读者(以及您自己)未来)。
你为什么要这样做?
std::less
存在仅用于两个目的:
用户没有理由重载它 - 重载operator<
或使用自定义比较器函数。
有一些标准算法可以被合理地特化std::swap
是一个很好的例子——为此你需要在命名空间 std 中声明特化。
less 函子不必在std
命名空间中。 所以
struct A
{
A(int _v=0):v(_v){}
int v;
};
template<> struct less<A>
{
bool operator()(const A& k1, const A& k2) const
{
return k1.v < k2.v;
}
};
std::map<A,int> m;
m[A(1)] = 1;
m[A(2)] = 2;
按预期工作。 (调用您刚刚创建的函子)。
我想您已经知道了,但是您可以编写自己的 operator<(k1,k2),这就是默认的 less 函子要查找的内容。
bool operator<(const DateTimeKey & k1, const DateTimeKey & k2)
{
//your code...
}
即使其他人已经回答了这个问题,并回答了如何专门化std::less
(通过将它们包装在命名空间块中)和正确的方法(重载operator <
)。
但是, C++
现在允许(在C++11
)按照您在第一个示例中所做的方式进行规范。
显式特化应在包含特化模板的命名空间中声明。 其 declarator-id 未限定的显式特化应在模板的最近封闭命名空间中声明,或者,如果命名空间是内联的 (7.3.1),则应在其封闭命名空间集中的任何命名空间中声明。 这样的声明也可以是定义。 如果声明不是定义,则可以稍后定义特化(7.3.1.2)。
我在我的Ubuntu
机器上用g++ (8.3.0)
尝试了以下代码。
#include <iostream>
#include <map>
#include <string>
#include <algorithm>
class myType {
public:
myType(int in): i_(in) { }
int i_;
};
template <>
struct std::less<myType> {
bool operator()(const myType& a, const myType& b) const
{
return a.i_ < b.i_;
}
};
int main(int argc, char *argv[])
{
std::map<myType, std::string> vector = { { 1, "1"}, { 2, "2"}, { 3, "3"}, { 0, "0" } };
for (auto& i: vector)
std::cout << i.first.i_ << std::endl;
return 0;
}
上面的代码是用
g++ --std=c++11 compare.cpp -Wall
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.