Storage
,其中有一个方法可以聚合指向某些Objects
的指针到一个向量中。就像这样:class Storage
{
public:
std::vector<Object*> aggregate_some_objects(); // non-const version
std::vector<const Object*> aggregate_some_objects() const; // const version
private:
std::unordered_map<size_t, Object> m_objects; // data is stored
// by-value in a non-vector container
}
通常情况下,可以通过使用const_cast
在一个方法中调用另一个方法来避免在实现const +非const方法对时进行复制粘贴。但是在这种情况下不可能这样做,因为这两个方法的返回类型不同。
避免复制粘贴的最直接的方法是从非const
版本调用const
版本,并使用返回的std::vector<const T*>
填充一个单独的std::vector<T*>
。但是这将导致至少2次堆分配(每个向量一次)。我想避免与第二个向量相关联的分配。
我想知道是否有办法编写类似于
template <typename T>
std::vector<T*> remove_const_from_vector_of_ptrs(std::vector<const T*>&& input)
{
std::vector<T*> ret;
// do some magic stuff here that does not involve
// more memory allocations
return ret;
}
因此,允许编写。
std::vector<const Object*> Storage::aggregate_some_objects() const
{
// non-trivial implementation
}
std::vector<Object*> Storage::aggregate_some_objects()
{
auto objects = const_cast<const Storage*>(this)->aggregate_some_objects();
return remove_const_from_vector_of_ptrs(std::move(objects));
}
std::vector
没有像std::unique_ptr
那样的'release'方法,允许转移内存所有权,这是有很好的原因的,所以我认为这是不可能的。
我也明白,如果可能的话,这将是一种危险的操作,应该尽量避免,就像const_cast
一样。但在像这样的情况下仔细使用似乎比复制粘贴更有益。
编辑:添加了对“额外”分配的澄清,并将Storage :: aggregate_objects()
更改为Storage :: aggregate_some_objects()
,以更好地指示这些方法的实现比基于范围的循环更复杂-因此希望避免复制粘贴实现。
vector::reserve
)。我所说的是在涉及非const
版本调用const
版本(它返回std::vector<const T*>
)并填充单独的std::vector<T*>
的问题的最简实现中将发生的分配。创建一个单独的向量将导致至少1个额外的分配,我想避免这种情况。在问题中澄清了这一点。 - Sergey Nikitinstd::vector<T*>
的函数模板,然后使用T
==Object
或T
==const Object
调用它即可。 - Jonathan Wakely