Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用std::complex<;双倍>;作为std::map键_C++_C++11_Stdmap - Fatal编程技术网

C++ 使用std::complex<;双倍>;作为std::map键

C++ 使用std::complex<;双倍>;作为std::map键,c++,c++11,stdmap,C++,C++11,Stdmap,如何使用复数作为地图中的键?以下是一个不会编译的小示例: #include <complex> #include <map> int main() { std::complex<double> zero = 0.0; std::map<std::complex<double>, int> theMap; return (theMap.count(zero)); } #包括 #包括 int main(){ 标准:复零=0.0

如何使用复数作为地图中的键?以下是一个不会编译的小示例:

#include <complex>
#include <map>
int main() {
  std::complex<double> zero = 0.0;
  std::map<std::complex<double>, int> theMap;
  return (theMap.count(zero));
}
#包括
#包括
int main(){
标准:复零=0.0;
std::映射主题图;
返回(映射计数(零));
}
我可以创建没有错误的映射,但是任何方法(例如上面的
count
调用以及
find
[]
操作符,
insert
等)都会生成编译时错误。这肯定是我理解上的一个问题,因为我使用clang和g++得到了类似的结果

看起来编译器无法比较两个复数。我创建了所有的比较运算符(例如,
bool运算符<(const std::complex&lhs,const std::complex&rhs){return(std::norm(lhs)
),用于比较复数(只要你不介意
3<-5
为真,这对于
map
,应该没问题),但是编译器没有把它捡起来


我对无序映射也有类似的问题(对于
complex
没有散列)

我没有查看实现,但根据cppreference,使用
std::less
作为比较运算符,可能不是专门用于
std::complex
,如果在模板
std::map
中实现一个pass,并将其作为第三个参数,则可以提供一个hash函子和一个equality函子。如果这两个都实现了,您可以使用
std::complex
作为键。

主要答案已在上面的评论中指出。问题是复数没有排序,因此对于
std::complex
,没有预定义的较小运算符。不过,您可以自己定义一个,通过使用已经为
std::array
:

#包括
#包括
#包括
#包括

#include.

您的方法的问题是,对于已排序的容器,例如
std::map
,密钥必须服从严格的弱排序。发件人:

严格弱序具有以下性质。对于S中的所有x和y

对于所有x,x 对于所有的x,y,如果x 对于所有x、y和z,如果x 对于所有x、y和z,如果x与y不可比,y与z不可比,那么x与z不可比(不可比的传递性)

不幸的是,没有一种自然的方式对复数施加严格的弱序。例如,1是 您需要使用复数作为键,不太可能需要和已排序的容器。尝试查看
std::无序的\u映射

来自C++11标准第23.2.4.2节[associative.reqmts]:


每个关联容器都在键和排序关系比较上参数化,从而在键的元素上产生严格的弱排序(25.4)。此外,map和multimap将任意类型的T与键相关联。Compare类型的对象称为容器的comparison对象。

您不介意在您的比较方案中
1==-1==i==-i
(它们都等于许多其他复数)?您将只能在地图中插入其中一个。当然,其他所有等式集也是如此。欢迎使用StackOverflow。具体来说,你会得到哪些错误?考虑使用<代码>(LHS。Real.)(RHS.Real.()){(LHS。Real.)= = RHS.Real.(和)和LHS.IMAGE()(RHS.IMAGE())< /代码>。@ WhozCraig在复数上没有自然排序。同样地,对于
std::complex
类型,没有内置的比较运算符(除了
=
!=
),TimothyShields我切换为strict
std=c++11
和kerboom,如果
std::less
没有明确的专门化,则没有
运算符,然后它将执行
lhs
(这也不是为
std::complex
定义的)。但是,关于解决方案是第三个模板参数,您是对的。我很好奇,您现在是说,如果实现了
std::less
,那么
lhs
是有效的,即使没有
运算符,也很抱歉造成混淆。实现提供了一种新的方法。因此,如果没有更好的
std::less
专门化,就像在本例中和
std::less
一样,那么它默认为提到的专门化。该专门化将尝试执行将失败的
lhs
。基本上,这就是为什么错误消息是
std::complex
没有实现
lhs
,而不是
std::less
不存在。不允许您将自己的内容添加到命名空间中std@Matt麦克纳布:你说得对,因为
std::complex
不是用户定义的类型。我通过删除
namespace std
编辑了我的答案。关于向
namespace std
添加内容,请参见,其中说明只能对用户定义的类型进行专门化(而
std::complex
则不可能)。然而,在中,有人指出,尽管这是未定义的行为,但现代编译器允许这样做(除非这种专门化已经存在)。。。这就是它在这里工作的原因。@davidhigh,容器的内部算法假定传递性。可以将其视为构造容器对象的先决条件。标准词典排序——尽管在代数中有点无用——满足了规定的要求。这是通过比较我在回答中使用的
std::array
来完成的。@davidhigh,没有逻辑或数学上的理由支持实数行而不是复数行,这正是排序所做的。例如
#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;
}