Reputation: 13575
I want to implement a sorted pointer vector, like the following
#include <vector>
#include <memory>
#include <algorithm>
//! A random accessed vector with sorted allocated elements.
//! - Elements must be allocated on heap.
//! - The vector manages the memories of its elements.
template<class T, class Compare = std::less<T>>
class SortedPtrVector
{
public:
SortedPtrVector() {}
//! Add an element, return its index.
int Add(T* element)
{
auto position = std::lower_bound(m_vector.begin(), m_vector.end(),
element, Compare); // Wrong here due to compare smart pointers
auto newPosition = m_vector.insert(position, element);
return newPosition - m_vector.begin();
}
private:
std::vector<std::unique_ptr<T>> m_vector;
};
How to implement the Add function? Thanks a lot.
Upvotes: 1
Views: 454
Reputation: 361412
auto position = std::lower_bound(m_vector.begin(), m_vector.end(),
element, Compare);
This is obviously wrong. Compare
is a type, not an object.
You could use lambda with an object of Compare
. So I think this should work:
Compare cmp;
auto comparer = [&](std::unique_ptr<T> const & a, std::unique_ptr<T> const & b)
{
return cmp(*a, *b); //use cmp here!
};
std::unique_ptr<T> uniqElem(element);
auto position = std::lower_bound( m_vector.begin(),
m_vector.end(),
uniqElem, //not element!!
comparer);
Note that you cannot pass element
to std::lower_bound
, as element
is of type T*
, when the std::lower_bound
expects the value of type std::unique_ptr<T>
and there is no implicit conversion from T*
to std::unique_ptr<T>
. Also, you cannot insert element
to the vector for the same reason. Insert uniqElem
to the vector.
I would suggest you to take the argument as unique_ptr
instead of T*
, because that indicates to the user that the added item will be deleted automatically when an object of SortedPtrVector
goes out of scope:
int Add(T* element); //bad - doesn't say element will be deleted!
int Add(std::unique_ptr<T> element); //good - says element will be deleted!
If you use std::unique_ptr<T>
as parameter type, then note these points:
v.Add(new T()); //will not work
v.Add(std::unique_ptr<T>(new T()); //will work
std::unique_ptr<T> item(new T());
v.Add(item); //will not work
v.Add(std::move(item)); //will work
It is all because std::unique_ptr
is NOT copyable, but it is moveable.
Upvotes: 1
Reputation: 81349
Instead of using std::less
you can implement your own ptr_less
like this:
template< typename T >
class ptr_less
{
typedef bool result_type;
bool operator ()( T const& left, T const& right ) const
{
return *left < *right;
}
};
A general implementation would have to check for null pointers as well.
Another approach would be to use boost::ptr_vector
instead of std::vector
.
Upvotes: 1