使用 std::complex<double> 作为 std::map 键
Using std::complex<double> as a std::map key
如何在地图中使用复数作为键? 这是一个不会编译的小示例:
#include <complex>
#include <map>
int main() {
std::complex<double> zero = 0.0;
std::map<std::complex<double>, int> theMap;
return (theMap.count(zero));
}
我可以毫无错误地创建映射,但是任何方法(例如,上面的count
调用以及find
、[]
运算符、insert
等(都会产生编译时错误。 这绝对是我的理解问题,因为我使用 clang 和 g++ 得到了类似的结果。
看起来编译器无法比较两个复数。 我创建了所有的比较运算符(例如,bool operator< (const std::complex & lhs, const std::complex & rhs) {return (std::norm(lhs) < std::norm(rhs));}
(,它适用于比较复数(只要你不介意3 < -5
为真,这对map
来说应该没问题(,但编译器不会拾取它。
我在unordered_map方面有类似的问题(complex<double>
没有哈希
你的方法的问题在于,对于有序容器,例如 std::map
,密钥必须适合严格的弱排序。来自维基百科:
严格的弱排序具有以下属性。对于 S 中的所有 x 和 y,
对于所有 x,并不是 x <x(自反性(。>
对于所有 x,y,如果 x <y,则><x(不对称(的情况并非如此。>
对于所有 x、y 和 z,如果 x
您需要使用复数作为键,您不太可能需要和有序容器。尝试查看std::unordered_map
。
来自 C++11 标准的第 23.2.4.2 节 [associaciative.reqmts]:
每个关联容器都在 Key 和排序关系 Compare 上参数化,该关系在 Key 的元素上诱导严格的弱排序 (25.4(。此外,映射和多重映射将任意类型 T 与键相关联。比较类型的对象称为容器的比较对象。
我没有看过实现,但根据 cppreference std::map
使用 std::less<T>
作为比较运算符,这可能不是专门用于std::complex
的,如果你实现一个传递它作为模板中的第三个参数,std::map<std::complex, int, LessOperator>
与 std:unordered_map
类似,您可以在其中提供哈希函子和相等函子。如果两者都实现了,则可以使用 std::complex
作为键。
主要答案已在上面的评论中指出。问题是复数不是有序的,因此没有预定义的std::complex<T>
较小运算符。不过,您可以为自己定义一个,这很容易通过使用已经定义的较小运算符来std::array<T,2>
:
#include <iostream>
#include<complex>
#include<map>
#include<unordered_map>
#include<array>
template<typename T> struct less {};
template<typename T>
struct less<std::complex<T> >
{
bool operator()(std::complex<T> const& a, std::complex<T> const& b)
{
return std::array<T,2>{a.real(),a.imag()} < std::array<T,2>{b.real(),b.imag()};
}
};
int main()
{
std::map<std::complex<double>, int, less<std::complex<double> > > m;
m[std::complex<double>(1.0,0.0)]=1;
m[std::complex<double>(0.0,1.0)]=2;
m[{0.5,0.5}]=3;
return 0;
}
在此处查看实时示例。
- C++匿名结构作为std::映射值
- 为什么 std::function 可以作为 std::not2 的参数?
- std::vector::迭代器是否可以合法地作为指针
- 转换函数,将 std::数组的双精度作为参数或双精度作为参数单独转换
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- std::ofstream 作为类成员删除复制构造函数?
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- std::span<const T> 作为函数模板中的参数
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 使用 std::async 时死锁,将来作为成员
- 为什么我不能将引用作为 std::async 的函数参数传递
- 我可以将向量作为initial_sum和不同的函数传递给 std::累积吗?
- 如何使用 std::string 作为 QHash 的键?
- C++ 事件管理器的回调,使用 std::function 和 std:bind 以及派生类作为参数
- 传递 std::数组变量作为参数
- std::string 可以作为 nlohmann::json 传递给显式构造函数
- 是否可以使用 std::array 作为 POD 结构的数据容器?
- 附加使用 Struct 作为"multikey"并将 std::vector 用作映射值的映射
- std::p作为 std 中定义的unordered_map自定义键的字符串的空气失败并出现模板错误
- 我想从这段代码中删除使用命名空间std,但我不确定什么都需要用std::作为前缀