我需要按Blah的整数id对自定义类型std::vector<Blah> v
的矢量进行排序。我是通过std::sort(v.begin(), v.end())
执行此操作,操作符<
在Blah
内被重载为
bool operator< (const Blah& b) const { return (id < b.id); }
我注意到Blah的私有ID不能声明为const int id
,否则Blah
类型不符合std::sort
的要求(我认为它与不存在冲突ValueSwappable?)
如果id
不是const
,一切都很好。但是,我不喜欢没有常数id的对象的想法只是为了在向量中重新排列它们的顺序。
有办法解决这个问题吗?
答案 0 :(得分:1)
有办法解决这个问题吗?
我担心这就是它的样子。如果你想对矢量(原则上是一个数组)进行排序,那么在交换它们时你必须指定元素。
至少这就是我的想法,实际上你可以作弊。将你的对象包装成一个联合:
template<typename T>
union ac {
// actual object
T thing;
// assignment first destructs object, then copy
// constructs a new inplace.
ac & operator=(ac<T> const & other) {
thing. ~T();
new (& thing) T(other. thing);
}
// need to provide constructor, destructor, etc.
ac(T && t) : thing (std:: forward<T>(t))
{}
ac(ac<T> const & other) : thing (other. thing) {}
~ac() {
thing. ~T();
}
// if you need them, add move assignment and constructor
};
然后,您可以实现(复制)赋值运算符,首先破坏当前对象,然后(复制)从旧对象提供的位置构造一个新对象。
您还需要提供构造函数和析构函数,当然这仅适用于C ++ 11及更高版本,因为先前语言标准中的union成员存在限制。
这看起来很不错:Live demo.
但是,我认为你应该首先重新审视一些设计选择,例如:如果常量id确实需要成为对象的一部分
答案 1 :(得分:0)
有办法解决这个问题吗?
所以你想要更新/交换一个对象的整个数据(包括它的身份)并保持身份不变;这两者是冲突的,因为常数意味着“不改变”(而交换意味着“改变这些实例”)。
你偶然发现了const-ness的两个(竞争)定义:概念常量(数据表示/表示的是相同的)和二进制常量(表示数据的字节不会改变)。 (第一个定义是导致在语言中引入可变性的原因:在破坏二进制常量的同时保持概念常数的能力)。
这里的数据在概念上是恒定的(数据的接口应该是常量)但不是二进制常量(你可以交换值,所以你的位可能会转移到另一个实例)。
对此的规范思想是在内部保持数据非const,并且仅为客户端代码提供const public / protected访问。
你说:
但是,我不喜欢对象没有常数id的想法只是为了在向量中重新排列它们的顺序。
仅仅因为身份在概念上是不变的(暴露的API是/应该是不变的),你没有实际的硬性要求来保持数据不变(并且根据API不应该偏向它)。