按常量id排序自定义类型的向量



我需要按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的想法。

有别的办法吗?还是事情就是这样?

有别的办法吗?还是事情就是这样?

恐怕事情就是这样。如果要对vector(原则上是数组)进行排序,则必须在交换元素时将赋值给

至少我是这么想的,其实你可以稍微作弊一下。将你的对象包装成一个联合:

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及以上版本。

这似乎工作得很好:现场演示。

但是,我仍然认为你应该首先重新审视一些设计选择,例如,如果常量id确实需要成为对象的一部分

有别的办法吗?还是事情就是这样?

所以你想要更新/交换对象的整个数据(包括它的标识),并保持标识不变;这两者是冲突的,因为constant的意思是"不改变"(而swap的意思是"改变这些实例")。

你在这里遇到了const-ness的两个(相互竞争的)定义:概念const-ness(数据所说/意味着的是相同的)和二进制const-ness(表示数据的字节不改变)。(第一个定义导致了在语言中引入mutable:在打破二进制const-ness的同时保持概念上的const-ness的能力)

这里的数据在概念上是常量(与数据的接口应该是const),但不是二进制常量(您可以交换值,因此您的位可能会转移到另一个实例)。

规范的想法是在内部保持数据非const,并且仅为客户端代码提供const公共/受保护的访问。

你说:

但是,我不喜欢仅仅为了在vector中重新排列它们的顺序而不使用常量id的想法。

仅仅因为标识在概念上是恒定的(公开的API是/应该是恒定的),您没有实际的硬性要求来保持数据恒定(并且应该根据API对它没有偏好)。

最新更新