如何operator<在n元组上定义(例如在3元组上)以便它满足严格的弱排序概念?我知道boost库有正确定义的元组类,operator<但由于某些原因我无法使用它.
这是我之前提出的问题的后续问题"C++ 14标准库的哪些部分可能是什么以及将制作哪些部分constexpr?" 和" constexpr运营商超载指南?"
在运行时世界中,为多个数据成员的结构重载的operator<一个很好的习惯用法是std::tie将结构转换为a std::tuple并在其上进行捎带,operator<这就是Right Thing™(各种成员的字典比较).
在C++ 14,许多地方std::tuple制成constexpr,特别是make_tuple,std::get与前面提到的operator<.然而,似乎看似相关std::tie的没有标记constexpr.这很烦人,因为它使定义用户定义的文字类型在编译时可以比必要的更冗长.
问题:是否有任何技术原因std::tie未标记constexpr为C++ 14?
更新:LWG问题2301,在libc ++和libstdc ++ bug 65978中实现
更新2:在修改libstdc ++错误报告后,由@JonathanWakely修复了3个多小时!
我有以下运算符<应该首先按值排序,然后按另一个值排序:
inline bool operator < (const obj& a, const obj& b)
{
if(a.field1< b.field1)
return true;
else
return a.field2 < b.field2;
}
Run Code Online (Sandbox Code Playgroud)
我觉得这是不正确的,如果没有对成员变量进行另一次第三次比较测试,你就不能这样做,但我找不到任何不起作用的例子.那么这真的和预期的一样吗?谢谢
编辑:我会把它编码为:
inline bool operator < (const obj& a, const obj& b)
{
if(a.field1< b.field1)
return true;
else if(a.field1> b.field1)
return false;
else
return a.field2 < b.field2;
}
Run Code Online (Sandbox Code Playgroud)
有什么不同吗?我问,因为我知道我的经验是正确的,但也比第一个更长
我有一组3个整数的元组,我不想要任何重复.也就是说,我不希望2个条目具有相同的3个值.
这是我的代码.
struct Key{
unsigned a;
unsigned b;
unsigned c;
public:
Key(unsigned _a, unsigned _b, unsigned _c) :
a(_a),
b(_b),
c(_c) {}
bool operator<(const Key& rhs) const
{
if (a < rhs.a) {
return true;
}
if (b < rhs.b) {
return true;
}
if (c < rhs.c) {
return true;
}
return false;
};
};
std::set<Key> myset;
Run Code Online (Sandbox Code Playgroud)
但我myset有时会看到重复.我无法准确捕捉到什么序列导致添加重复条目.它并不总是发生.我的问题是,我的operator<功能有什么本质上的错误吗?
我正在处理点云,即点的向量,作为计算的结果,其包含重复点(高达云的大小的10%).
我的实现是根据x,y和z值对这些点进行排序,然后使用该std::unique函数.然而,生成的云仍然包含重复项,即使排序本身似乎有效.
这是至关重要的代码
bool comparePoint(pcl::PointXYZINormal p1, pcl::PointXYZINormal p2){
if (p1.x != p2.x)
return p1.x > p2.x;
else if (p1.y != p2.y)
return p1.y > p2.y;
else
return p1.z > p2.z;
}
bool equalPoint(pcl::PointXYZINormal p1, pcl::PointXYZINormal p2){
if (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z)
return true;
return false;
}
void KDsearch::cullDuplePoints(){
std::sort(points.begin(), points.end(), comparePoint);
std::unique(points.begin(), points.end(), equalPoint);
}
Run Code Online (Sandbox Code Playgroud)
这里是输出pointcloud(x,y和z坐标)的部分提取:
1.96828 -535.09515 2794.8391
1.96627 -636.95264 2914.0366
1.96627 -636.95264 2914.0366
1.9651 108.77433 2350.9841
1.9651 108.77433 2350.9841 …Run Code Online (Sandbox Code Playgroud) 有时我需要写一些丑陋的算符,
例如
lhs.date_ < rhs.date_ ||
lhs.date_ == rhs.date_ && lhs.time_ < rhs.time_ ||
lhs.date_ == rhs.date_ && lhs.time_ == rhs.time_ && lhs.id_ < rhs.id_ .....
Run Code Online (Sandbox Code Playgroud)
它让我非常恼火.
所以我开始避免写下面的内容:
std::make_tuple( lhs.date_, lhs.time_, lhs.id_ ) <
std::make_tuple(rhs.date_, rhs.time_, rhs.id_ );
Run Code Online (Sandbox Code Playgroud)
我几乎感到高兴,但请注意,我可能使用元组而不是他们的目的让我担心.
你能否批评这个解决方案?
或者这是一个很好的做法?
你怎么避免这种比较?
更新:
感谢指向std :: tie以避免复制对象.
并感谢指出重复的问题
如何概括<如果struct有任意多个数据成员(<将使用列出数据成员的顺序定义)?一个包含3个数据成员的简单示例:
struct nData {
int a;
double b;
CustomClass c; // with == and < defined for CustomClass
bool operator == (const nData& other) {return (a == other.a) && (b == other.b) && (c == other.c);}
bool operator < (const nData& other) {
if ( (a < other.a) || ((a == other.a) && (b < other.b)) ||
((a == other.a) && (b == other.b) && (c < other.c)) )
return true;
return false;
}
};
Run Code Online (Sandbox Code Playgroud)
以某种方式使用可变参数模板和递归?
我经常有一些类提供简单的逐个成员比较:
class ApplicationSettings
{
public:
bool operator==(const ApplicationSettings& other) const;
bool operator!=(const ApplicationSettings& other) const;
private:
SkinType m_ApplicationSkin;
UpdateCheckInterval m_IntervalForUpdateChecks;
bool m_bDockSelectionWidget;
// Add future members to operator==
};
bool ApplicationSettings::operator==(const ApplicationSettings& other) const
{
if (m_ApplicationSkin != other.m_ApplicationSkin)
{
return false;
}
if (m_IntervalForUpdateChecks != other.m_IntervalForUpdateChecks)
{
return false;
}
if (m_bDockSelectionWidget != other.m_bDockSelectionWidget)
{
return false;
}
return true;
}
bool ApplicationSettings::operator!=(const ApplicationSettings& other) const;
{
return ( ! operator==(other));
}
Run Code Online (Sandbox Code Playgroud)
鉴于此时C++没有提供任何构造来生成运算符==,是否有更好的方法来确保未来成员成为比较的一部分,而不是我在数据成员下面添加的注释?
我尝试使用定义为的地图:
map<Vertex,unsigned int> _addedVertices;
Run Code Online (Sandbox Code Playgroud)
现在,当我使用find函数检查顶点是否已经在里面时,我得到一个迭代器到一个具有不同信息的错误顶点,所以我尝试了以下内容:
map<Vertex,unsigned int,cmpByVertexFields> _addedVertices;
Run Code Online (Sandbox Code Playgroud)
这没有帮助.
我在Vertex类中有以下重载函数.
bool operator<(const Vertex &otherV)const{
return(_x<otherV._x && _y<otherV._y && _z<otherV._z);
}
bool operator==(const Vertex &otherV)const{
return _x==otherV._x && _y==otherV._y && _z==otherV._z;
}
Run Code Online (Sandbox Code Playgroud)
但没有任何作用.示例:我插入了一个包含(0.2,0.1,0.4)的顶点,接下来我使用的是查找函数(0.2,0.15,0.41)我得到的迭代器是第一个顶点而不是map.end().
我忘了定义什么?谢谢
编辑:cmpByVertexFields:
struct cmpByVertexFields {
bool operator()(const Vertex& a, const Vertex& b) const {
return a.getX()==b.getX() &&
a.getY()==b.getY() &&
a.getZ()==b.getZ();
}
};
Run Code Online (Sandbox Code Playgroud) 我尝试编写一个std :: map <Vector3D,double>,其中colinear(并行或反并行)向量应该共享相同的密钥.
作为比较函数,我使用以下函数(在isEqualEnough()中具有1e-9容差),这是我在std :: map中使用(数学)向量创建的
struct Vector3DComparator
{
bool operator() (const Vector3D& lhsIn, const Vector3D& rhsIn) const
{
Vector3D lhs = lhsIn.absolute(); // make all members positive
Vector3D rhs = rhsIn.absolute();
if ((lhs.z < rhs.z))
return true;
if ((isEqualEnough(lhs.z, rhs.z))
&& (lhs.y < rhs.y))
return true;
if ((isEqualEnough(lhs.z, rhs.z))
&& (isEqualEnough(lhs.y, rhs.y))
&& (lhs.x < rhs.x))
return true;
return false;
}
};
Run Code Online (Sandbox Code Playgroud)
当我将一个立方体的法线插入我的地图时,我应该得到3个不同的值(因为我不关心方向)但我得到4:
我有一个包含一些简单成员的类,并希望实现一个非常简单的<运算符.这就是我的开始:
inline bool operator< (const T& lhs, const T& rhs) { return std::tie(lhs.GetA(), lhs.GetB()) < std::tie(rhs.GetA(), rhs.GetB()); }
Run Code Online (Sandbox Code Playgroud)
视觉工作室抱怨
Warning 2 warning C4239: nonstandard extension used : 'argument' : conversion from 'A' to 'A &'
Run Code Online (Sandbox Code Playgroud)
似乎问题是我没有使用成员,而是使用函数,并且正在将rvalue传递给非const ref.我想我可以在本地A中保存GetA(),但不愿意.
我该如何解决?
我尝试添加
A& GetARef() const { return a; }
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为我试图返回一个非const引用与const.
A& GetARef() { return a; }
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为lhs并且rhs是常量.
现在我想也许我应该使用std::tuple或者可能std::tie( std::cref(lhs.GetA()) ),或者可能是一个新模板
template < typename... T >
std::tuple<const T&...> ctie( const T&... args )
{ …Run Code Online (Sandbox Code Playgroud)