我需要按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对它没有偏好)。