我专注于数据类型的'less'(谓词)。
代码如下所示:
template<>
struct std::less<DateTimeKey>
{
bool operator()(const DateTimeKey& k1, const DateTimeKey& k2) const
{
// Some code ...
}
}
编译时(在Ubuntu 9.10上使用g ++ 4.4.1),我收到错误:
不同命名空间中“template struct std :: less”的专业化
我做了一些研究,发现有一个“解决方法”涉及将特化包装在std命名空间中 - 即将代码更改为:
namespace std {
template<>
struct less<DateTimeKey>
{
bool operator()(const DateTimeKey& k1, const DateTimeKey& k2) const
{
// Some code ...
}
}
}
确实会关闭编译器。然而,这个解决方案来自一个5岁的职位(由'伟大的'Victor Bazarof而不是[双关语])。这个修复方法还有很长的路要走,还是有更好的方法来解决这个问题,还是“老方法”仍然有效?
答案 0 :(得分:24)
这仍然是这样做的方法。遗憾的是,您不能像在类中那样声明或定义命名空间中的函数:您需要将它们实际包装在命名空间块中。
答案 1 :(得分:23)
如果需要专门化标准算法,可以在std命名空间中执行此操作。根据标准,这是唯一允许您在该命名空间内执行的操作。
[lib.reserved.names] / 1
对于C ++程序来说,它是未定义的 添加声明或定义 命名空间std或命名空间 命名空间std除非另有说明 指定。程序可以添加模板 任何标准的专业化 库模板到命名空间std。 这样的专业化(完整或 部分)标准库 模板导致未定义的行为 除非声明取决于a 用户定义的外部链接名称 除非专业化会议 标准库要求 原始模板
现在,问题是你是否真的想要专攻std::less
。请注意,std::less
将调用为您的类型定义的比较运算符,因此您可以提供该操作,而不是专门化模板。
针对您的特定类型专门设置std::less
的问题是,如果您提供的操作与operator<
针对您的类型执行的操作不同,则会导致混淆。如果它们执行相同的操作,只需保留默认的std::less
定义而不需要专门化。
如果您不想提供比较运算符,但仍希望在关联容器中使用类型或使用需要比较器的算法,则可以通过其他名称提供外部比较仿函数,这不会混淆其他读者(和你自己在未来的某个地方。)
答案 2 :(得分:3)
较少的仿函数不必位于 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;
按预期工作。 (调用刚创建的仿函数)。
我猜你已经知道了,但是你可以编写自己的运算符&lt;(k1,k2),这是默认的较少的函子所寻找的。 p>
bool operator<(const DateTimeKey & k1, const DateTimeKey & k2)
{
//your code...
}
答案 3 :(得分:3)
你为什么要这样做?
std::less
仅用于两个目的:
用户没有理由重载它 - 重载operator<
或使用自定义比较器功能。
有std算法可以明智地专门化 - std::swap
是一个很好的例子 - 为此你需要在命名空间std中声明特化。
答案 4 :(得分:0)
即使其他人回答了该问题,也提供了有关如何专门化std::less
的答案(通过将它们包装在名称空间块中)以及正确的方法(重载operator <
)。 / p>
但是,C++
现在允许(在C++11
中)以您在第一个示例中的方式为特色。
显式专门化应在包含专门化模板的命名空间中声明。声明符ID不合格的显式专门化应在模板的最近封闭命名空间中声明,或者,如果命名空间是内联(7.3.1),则应在其封闭命名空间集中声明任何命名空间。这样的声明也可以是定义。如果声明不是定义,则可以稍后定义专门化(7.3.1.2)。
我在g++ (8.3.0)
的计算机上使用Ubuntu
尝试了以下代码。
#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