按常量ID

时间:2015-08-11 08:38:20

标签: c++ sorting vector

我需要按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的对象的想法只是为了在向量中重新排列它们的顺序。

有办法解决这个问题吗?

2 个答案:

答案 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不应该偏向它)。