如果性能没有问题:
auto idx_of = [&](X const* p) {
return std::distance(begin(const_ptrs), std::find(begin(const_ptrs), end(const_ptrs), p));
};
std::sort(begin(uniq_ptrs), end(uniq_ptrs), [&](std::unique_ptr<X> const& a, std::unique_ptr<X> const& b) {
return idx_of(a.get()) < idx_of(b.get());
});
如果性能是一个问题,请使用您的中间映射:
hash_map<const X*, int> indices;
for (auto i = 0u; i < const_ptrs.size(); ++i) {
indices[const_ptrs[i]] = i;
}
std::sort(begin(uniq_ptrs), end(uniq_ptrs), [&](std::unique_ptr<X> const& a, std::unique_ptr<X> const& b) {
return indices[ a.get() ] < indices[ b.get() ];
});
---如果您完全确定指针集匹配,您可以作弊并即时创建全新的 unique_ptrs 。--- 嗯,因为 const,就像您说的那样,它不起作用。
更新如果性能在这里领先,只需删除 const。如果您知道对象实际上不是const,则可以使用邪恶const_cast<>
查看所有三种方法:住在 Coliru
#include <unordered_map>
#include <algorithm>
#include <memory>
#include <vector>
#include <cassert>
template <typename K, typename V>
using hash_map = std::unordered_map<K,V>;
struct X{};
int main()
{
std::vector<std::unique_ptr<X>> uniq_ptrs;
std::vector<const X*> const_ptrs;
// naive approach, no performance worries
auto idx_of = [&](X const* p) {
return std::distance(begin(const_ptrs), std::find(begin(const_ptrs), end(const_ptrs), p));
};
std::sort(begin(uniq_ptrs), end(uniq_ptrs), [&](std::unique_ptr<X> const& a, std::unique_ptr<X> const& b) {
return idx_of(a.get()) < idx_of(b.get());
});
// less naive approach, no performance worries
hash_map<const X*, int> indices;
for (auto i = 0u; i < const_ptrs.size(); ++i) {
indices[const_ptrs[i]] = i;
}
std::sort(begin(uniq_ptrs), end(uniq_ptrs), [&](std::unique_ptr<X> const& a, std::unique_ptr<X> const& b) {
return indices[ a.get() ] < indices[ b.get() ];
});
// cheating! only not UB if you know the objects aren't "physically" const
assert(const_ptrs.size() == uniq_ptrs.size());
for (auto i = 0u; i < const_ptrs.size(); ++i) {
uniq_ptrs[i].release();
uniq_ptrs[i].reset(const_cast<X*>(const_ptrs[i]));
}
}