I'm working on a file, Deque.hpp, which uses an iterator class and Nodes to make a deque, but I'm getting the error:
"Error C1004 unexpected end-of-file found "
I can't seem to find what's causing this. Here's my code.
#ifndef DEQUE_H
#define DEQUE_H
#include <iostream>
#include <new>
#include <cstdlib>
#include <algorithm>
//
//
//
template <typename T>
class Deque
{
public:
Deque();
Deque(const Deque & rhs);
~Deque();
Deque & operator= (const Deque & rhs);
Deque(Deque && rhs) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail };
Deque & operator= (Deque && rhs);
T & Deque<T>::operator[](int n);
Iterator begin();
const_iterator begin() const;
Iterator end();
const_iterator end() const;
int size() const;
bool isEmpty() const;
void clear();
T & left();
const T & left() const;
T & right();
const T & right() const;
void pushLeft(const T & x);
void pushLeft(T && x);
void pushRight(const T & x);
void pushRight(T && x);
T & popLeft();
T & popRight();
bool Deque<T>::contains(const T&);
struct Node
{
T data;
Node *prev;
Node *next;
Node(const T & d = T{}, Node * p = NULL, Node * n = NULL) :
data{ d }, prev{ p }, next{ n } {}
Node(T && d, Node * p = NULL, Node * n = NULL)
: data{ std::move(d) }, prev{ p }, next{ n } {}
};
class const_iterator
{
public:
const_iterator() : current{ NULL } { }
const T & operator* () const;
const_iterator & operator++ ();
const_iterator & operator-- (); //!
const_iterator operator++ (int);
const_iterator operator-- (int); //!
bool operator== (const const_iterator & rhs) const;
bool operator!= (const const_iterator & rhs) const;
protected:
Node *current;
T & retrieve() const;
const_iterator(Node *p) : current{ p } { }
friend class Deque<T>;
};
class Iterator : public const_iterator
{
public:
Iterator();
T & operator* ();
const T & operator* () const;
Iterator & operator++ ();
Iterator & operator-- (); //!
Iterator operator++ (int);
Iterator operator-- (int); //!
protected:
Iterator(Node *p) : const_iterator{ p } { }
friend class Deque<T>;
};
private:
// Insert x before itr.
Iterator insert(Iterator itr, const T & x);
// Insert x before itr.
Iterator insert(Iterator itr, T && x);
// Erase item at itr.
Iterator erase(Iterator itr);
Iterator erase(Iterator from, Iterator to);
int theSize;
Node *head;
Node *tail;
void init();
};
template<typename T>
inline const T & Deque<T>::const_iterator::operator*() const
{
return retrieve();
}
template<typename T>
inline const_iterator & Deque<T>::const_iterator::operator++()
{
current = current->next;
return *this;
}
template<typename T>
inline const_iterator & Deque<T>::const_iterator::operator--()
{
current = current->prev;
return *this;
}
template<typename T>
inline const_iterator Deque<T>::const_iterator::operator++(int)
{
const_iterator old = *this;
++(*this);
return old;
}
template<typename T>
inline const_iterator Deque<T>::const_iterator::operator--(int)
{
const_iterator old = *this;
--(*this);
return old;
}
template<typename T>
inline bool Deque<T>::const_iterator::operator==(const const_iterator & rhs) const
{
return current == rhs.current;
}
template<typename T>
inline bool Deque<T>::const_iterator::operator!=(const const_iterator & rhs) const
{
return !(*this == rhs);
}
template<typename T>
inline T & Deque<T>::const_iterator::retrieve() const
{
return current->data;
}
template<typename T>
inline Deque<T>::Iterator::Iterator()
{
}
template<typename T>
inline T & Deque<T>::Iterator::operator*()
{
return const_iterator::retrieve();
}
template<typename T>
inline const T & Deque<T>::Iterator::operator*() const
{
return const_iterator::operator*();
}
template<typename T>
inline Iterator & Deque<T>::Iterator::operator++()
{
this->current = this->current->next;
return *this;
}
template<typename T>
inline Iterator & Deque<T>::Iterator::operator--()
{
this->current = this->current->prev;
return *this;
}
template<typename T>
inline Iterator Deque<T>::Iterator::operator++(int)
{
Iterator old = *this;
++(*this);
return old;
}
template<typename T>
inline Iterator Deque<T>::Iterator::operator--(int)
{
Iterator old = *this;
--(*this);
return old;
}
template<typename T>
inline Deque<T>::Deque()
{
init();
}
template<typename T>
inline Deque<T>::~Deque()
{
clear();
delete head;
delete tail;
}
template<typename T>
inline Deque & Deque<T>::operator=(const Deque & rhs)
{
if (this == &rhs)
return *this;
clear();
for (const_iterator itr = rhs.begin(); itr != rhs.end(); ++itr)
pushRight(*itr)
return *this;
}
template<typename T>
inline Deque<T>::Deque(Deque && rhs)
{
rhs.theSize = 0;
rhs.head = NULL;
rhs.tail = NULL;
}
template<typename T>
inline Deque & Deque<T>::operator=(Deque && rhs)
{
std::swap(theSize, rhs.theSize);
std::swap(head, rhs.head);
std::swap(tail, rhs.tail);
return *this;
}
template<typename T>
inline T & Deque<T>::operator[](int n)
{
Iterator itr = begin();
for (int i = 0; i < n; i++)
{
itr.current = itr.current->next;
}
return itr.current->data;
}
template<typename T>
inline Iterator Deque<T>::begin()
{
return{ head->next };
}
template<typename T>
inline const_iterator Deque<T>::begin() const
{
return{ head->next };
}
template<typename T>
inline Iterator Deque<T>::end()
{
return{ tail->prev }; //changed to -> prev
}
template<typename T>
inline const_iterator Deque<T>::end() const
{
return{ tail->prev };
}
template<typename T>
inline int Deque<T>::size() const
{
return theSize;
}
template<typename T>
inline bool Deque<T>::isEmpty() const
{
return size() == 0;
}
template<typename T>
inline void Deque<T>::clear()
{
while (!isEmpty())
popLeft();
}
template<typename T>
inline T & Deque<T>::left()
{
return *begin();
}
template<typename T>
inline const T & Deque<T>::left() const
{
return *begin();
}
template<typename T>
inline T & Deque<T>::right()
{
return *end(); // deleted "--*end"
}
template<typename T>
inline const T & Deque<T>::right() const
{
return *end();
}
template<typename T>
inline void Deque<T>::pushLeft(const T & x)
{
insert(begin(), x);
}
template<typename T>
inline void Deque<T>::pushLeft(T && x)
{
insert(begin(), std::move(x)); // changed std::move(x)) to x
}
template<typename T>
inline void Deque<T>::pushRight(const T & x)
{
insert(end(), x);
}
template<typename T>
inline void Deque<T>::pushRight(T && x)
{
insert(end(), std::move(x));
}
template<typename T>
inline T & Deque<T>::popLeft()
{
return *begin(); erase(begin());
}
template<typename T>
inline T & Deque<T>::popRight()
{
return *end(); erase(end()); // changed --end to end
}
template<typename T>
inline bool Deque<T>::contains(const T &)
{
// stuff here
}
template<typename T>
inline Iterator Deque<T>::insert(Iterator itr, const T & x)
{
Node *p = itr.current;
theSize++;
return{ p->prev = p->prev->next = new Node{ x, p->prev, p } };
}
template<typename T>
inline Iterator Deque<T>::insert(Iterator itr, T && x)
{
Node *p = itr.current;
theSize++;
return{ p->prev = p->prev->next = new Node{ std::move(x), p->prev, p } };
}
template<typename T>
inline Iterator Deque<T>::erase(Iterator itr)
{
Node *p = itr.current;
Iterator retVal{ p->next };
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
theSize--;
return retVal;
}
template<typename T>
inline Iterator Deque<T>::erase(Iterator from, Iterator to)
{
for (Iterator itr = from; itr != to; )
itr = erase(itr);
return to;
}
template<typename T>
inline void Deque<T>::init()
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
template<typename T>
inline Deque<T>::Deque(const Deque & rhs)
{
init();
*this = rhs;
}
#endif
The first error to fix is the one identified by Algirdas Preidžius: your constructor has an initialization list but no body.
You should replace
Deque(Deque && rhs) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail };
by
Deque(Deque && rhs) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail } {};
Then you'll have a lot of other errors to fix. Good luck !
My advice when coding: write your code incrementaly, build and test regularly. You shouldn't have so much errors to fix at once !
By the way, any reason to not use std::deque ?
I am searching for template library with set-like container allowing searching by different key. I don't want map (key duplication) and want C++11 compliant code (C++14 added template<class K> iterator std::set::find(const K& x) which could be used in std::set<T*,my_transparent_deref_less<T*> > with custom compare functor).
Do you know such? Will boost add such or does it have already?
The signature should look like this: the_set<T, GetKey, Compare> and I want structure optimized for both size / memory usage (thus flat_set / btree_set) and speed of searching (insert/remove speed is not that critical). Example:
class User {
public:
User(const char *name);
const char *name();
... };
the_set<User*,const char*> USERS([](User* u) { u->name(); },
[](const char* lhs, const char* rhs) { strcmp(lhs, rhs) < 0; });
I have found red-black-tree in boost::detail that looks like what I want - the signature is template <class Key, class Value, class KeyOfValue, class KeyCompare, class A> class rbtree. Do we have something like that with flat_set and btree_set that I could use (without the fear of using something that is not to be used publicly but purposedly hidden as detail)?
Reason: I do plan to use such sets for many objects and many keys (possibly different keys/sets for same objects).
USERS, UNITS, ... - global using btree_set, possibly something like boost::multi_index
User::units, ... - sets in objects using flat_set
My code so far: (The problem is that I have to use StringWrapper now)
#include <set>
#include <iostream>
#include <type_traits>
#include "btree_set.h"
#include "boost/container/flat_set.hpp"
// dereferencing comparator
template <class T>
class less: public std::less<T> {
public:
typename std::enable_if<std::is_pointer<T>::value,
bool>::type operator() (T lhs, T rhs) const {
return *lhs < *rhs; }};
// here I can change underlying structure to btree_set or std::set
template <class T,
class C = less<T>,
class A = std::allocator<T> >
using default_set = boost::container::flat_set<T, C, A>;
// this works fine for classes derived from their primary key
template <class T, class K = T,
class B = default_set<K*> >
class object_set {
private:
typename std::enable_if<std::is_base_of<K, T>::value,
B>::type impl;
public:
template<class... Args>
T* add(K* key, Args&& ...args) {
auto it = impl.insert(key);
if (!it.second) return nullptr;
T* value = new T(*key, std::forward<Args>(args)...);
*it.first = value;
return value; }
T* operator[](K* key) {
auto it = impl.find(key);
if (it == impl.end()) return nullptr;
return (T*)*it; }
T* remove(K* key) {
auto it = impl.find(key);
if (it == impl.end()) return nullptr;
T* value = (T*)*it;
impl.erase(it);
return value; }
public:
template<class... Args>
T* add(K key, Args&& ...args) {
return add(&key, std::forward<Args>(args)...); }
T* operator[](K key) {
return (*this)[&key]; }
T* remove(K key) {
return remove(&key); }};
// workaround for above std::is_base_of constraint
class StringWrapper {
const char *data;
public:
StringWrapper(const char *data) {
this->data = data; }
operator const char *() const {
return data; }};
// example of class I want to use the container on
class User: public StringWrapper {
public:
User(const char *name): StringWrapper(name) {}};
// testing
object_set<User,StringWrapper> USERS;
int main() {
USERS.add("firda"); USERS.add("firda2");
User* firda = USERS["firda"];
delete USERS.remove(firda);
delete USERS.remove("firda2"); }
Sounds like a job for boost::multi_index
http://www.boost.org/doc/libs/1_55_0/libs/multi_index/doc/index.html
This is what I came with:
#include "boost/container/flat_set.hpp"
template<class T, class K, class GetKey, class CmpKey>
class fset {
private:
boost::container::container_detail::flat_tree<
K, T*, GetKey, CmpKey, std::allocator<T*> >
impl;
public:
template<class... Args>
T* add(K key, Args&& ...args) {
auto it = impl.lower_bound(key);
if (it != impl.end() && impl.key_comp()(key, GetKey()(*it))) {
return nullptr; }
T* value = new T(key, std::forward<Args>(args)...);
impl.insert_unique(it, value);
return value; }
T* operator[](K key) {
auto it = impl.find(key);
if (it == impl.end()) return nullptr;
return *it; }
T* remove(K key) {
auto it = impl.find(key);
if (it == impl.end()) return nullptr;
T* value = *it;
impl.erase(it);
return value; }};
class User {
private:
const char *name_;
public:
User(const char *name) {
std::size_t size = std::strlen(name) + 1;
char *buf = new char[size];
std::memcpy(buf, name, size);
name_ = buf; }
~User() {
delete[] name_; }
const char *name() const {
return name_; }
public:
struct get_name {
const char *operator()(User* u) const {
return u->name(); }};
struct cmp_name {
bool operator()(const char* lhs, const char* rhs) const {
return std::strcmp(lhs, rhs) < 0; }};};
fset<User,const char*,User::get_name,User::cmp_name>
USERS;
int main() {
USERS.add("firda");
User* firda = USERS["firda"];
delete USERS.remove("firda"); }
Should I close or delete this question now?
This is what I use now (look at struct vset_adaptor)
#ifndef HEADER___VECTSET___BE8EB41D7B3971E1
#define HEADER___VECTSET___BE8EB41D7B3971E1
#include <vector>
//############################################################### ptrvect
template <class T, class base = std::vector<T*> >
class ptrvect: public base {
public:
class iterator: public base::iterator {
friend class ptrvect;
private:
iterator(const typename base::const_iterator& it):
base::iterator(const_cast<T**>(&*it)) {
return; }
public:
iterator(const typename base::iterator& it):
base::iterator(it) {
return; }
T* operator->() const {
return **this; }};
class const_iterator: public base::const_iterator {
public:
const_iterator(const typename base::const_iterator& it):
base::const_iterator(it) {
return; }
const_iterator(const typename base::iterator& it):
base::const_iterator(it) {
return; }
T* operator->() const {
return **this; }};
template <class It = iterator>
class condpair: public std::pair<It,bool> {
public:
condpair(It it, bool second):
std::pair<It,bool>(it, second) {
return; }
T* operator->() const {
return *std::pair<It,bool>::first; }};
public:
iterator begin() {
return iterator(base::begin()); }
iterator end() {
return iterator(base::end()); }
const_iterator begin() const {
return const_iterator(base::begin()); }
const_iterator end() const {
return const_iterator(base::end()); }
public: // workarounds for pre-C++11 / bad C++11 implementation (should allow const_iterator)
iterator insert(const_iterator pos, T* value) {
return base::insert(iterator(pos), value); }
iterator erase(const_iterator pos) {
return base::erase(iterator(pos)); }
public: // addons
iterator find (T* key) {
return std::find(begin(), end(), key); }
const_iterator find (T* key) const {
return std::find(begin(), end(), key); }
bool contains (T* key) const {
return find(key) != end(); }
T* remove(T* key) {
auto it = find(key);
if (it == end()) return null;
T* val = *it;
base::erase(it);
return val; }
T* add(T* val) {
base::push_back(val);
return val; }
void release() {
for (T* it : *this) delete it;
base::clear(); }};
//########################################################## vset adaptor
template <class T, class K>
struct vset_adaptor {
K operator()(T* it) const {
return (K)(*it); }
bool operator()(K lhs, K rhs) const {
return lhs < rhs; }};
template <class T>
struct vset_adaptor<T,T*> {
T* operator()(T* it) const {
return it; }
bool operator()(T* lhs, T* rhs) const {
return lhs < rhs; }};
//================================================================== vset
template <class T, class K=T*, class F = vset_adaptor<T,K> >
class vset {
private:
ptrvect<T> impl;
struct Comp {
F f;
K operator()(T* it) const {
return f(it); }
bool operator()(K lhs, K rhs) const {
return f(lhs, rhs); }
bool operator()(T* lhs, K rhs) const {
return f(f(lhs), rhs); }
bool operator()(K lhs, T* rhs) const {
return f(lhs, f(rhs)); }
bool operator()(T* lhs, T* rhs) const {
return f(f(lhs), f(rhs)); }};
Comp comp;
public:
typedef typename ptrvect<T>::const_iterator iterator, const_iterator;
typedef unsigned size_type;
typedef T *value_type;
typedef K key_type;
typedef typename ptrvect<T>::template condpair<iterator> condpair;
public:
iterator begin() const {
return iterator(impl.begin()); }
iterator end() const {
return iterator(impl.end()); }
size_type size() const {
return impl.size(); }
bool empty() const {
return impl.empty(); }
public:
iterator lower_bound(K key) const {
return std::lower_bound(impl.begin(), impl.end(), key, comp); }
iterator upper_bound(K key) const {
return std::upper_bound(impl.begin(), impl.end(), key, comp); }
std::pair<iterator, iterator> equal_range(K key) const {
return std::equal_range(impl.begin(), impl.end(), key, comp); }
iterator find(K key) const {
iterator it = lower_bound(key);
return it == end() || comp(key, *it) ? end() : it; }
bool contains(K key) const {
iterator it = lower_bound(key);
return it != end() && !comp(key, *it); }
public:
typename std::enable_if<!std::is_same<T*,K>::value,
iterator>::type lower_bound(T* key) const {
return std::lower_bound(impl.begin(), impl.end(), comp(key), comp); }
typename std::enable_if<!std::is_same<T*,K>::value,
iterator>::type upper_bound(T* key) const {
return std::upper_bound(impl.begin(), impl.end(), comp(key), comp); }
typename std::enable_if<!std::is_same<T*,K>::value,
std::pair<iterator, iterator> >::type equal_range(T* key) const {
return std::equal_range(impl.begin(), impl.end(), comp(key), comp); }
typename std::enable_if<!std::is_same<T*,K>::value,
iterator>::type find(T* key) const {
iterator it = lower_bound(comp(key));
return it == end() || comp(key, *it) ? end() : it; }
public:
template<class... Args>
condpair emplace(K key, Args&& ...args) {
iterator it = lower_bound(key);
if (it == end() || comp(key, *it)) {
return condpair(impl.insert(it,
new T(key, std::forward<Args>(args)...)), true); }
return condpair(it, false); }
iterator erase(iterator at) {
return impl.erase(at); }
public:
T* add(T* value) {
iterator it = lower_bound(value);
if (it == end() || comp(comp(value), *it)) {
impl.insert(it, value);
return value; }
return nullptr; }
template<class... Args>
T* add(K key, Args&& ...args) {
iterator it = lower_bound(key);
if (it == end() || comp(key, *it)) {
T* value = new T(key, std::forward<Args>(args)...);
impl.insert(it, value);
return value; }
return nullptr; }
T* get(K key) const {
iterator it = find(key);
return it == impl.end() ? nullptr : *it; }
T* operator[](K key) const {
return *emplace(key).first; }
T* remove(K key) {
iterator it = find(key);
if (it == impl.end()) return nullptr;
T* value = *it;
impl.erase(it);
return value; }
typename std::enable_if<!std::is_same<T*,K>::value,
T*>::type remove(T* key) {
return remove(comp(key)); }
void release() {
for (T* it : *this) {
delete it; }
impl.clear(); }
void clear() {
impl.clear(); }};
#endif
....if you wonder about the codestyling, it is output of my own preprocessor. This is the real code:
#include <vector>
//############################################################### ptrvect
template <class T, class base = std::vector<T*> >
class ptrvect: public base
public:
class iterator: public base::iterator
friend class ptrvect
private:
iterator(const typename base::const_iterator& it):
base::iterator(const_cast<T**>(&*it))
return
public:
iterator(const typename base::iterator& it):
base::iterator(it)
return
T* operator->() const
return **this
class const_iterator: public base::const_iterator
public:
const_iterator(const typename base::const_iterator& it):
base::const_iterator(it)
return
const_iterator(const typename base::iterator& it):
base::const_iterator(it)
return
T* operator->() const
return **this
template <class It = iterator>
class condpair: public std::pair<It,bool>
public:
condpair(It it, bool second):
std::pair<It,bool>(it, second)
return
T* operator->() const
return *std::pair<It,bool>::first
public:
iterator begin()
return iterator(base::begin())
iterator end()
return iterator(base::end())
const_iterator begin() const
return const_iterator(base::begin())
const_iterator end() const
return const_iterator(base::end())
public: // workarounds for pre-C++11 / bad C++11 implementation (should allow const_iterator)
iterator insert(const_iterator pos, T* value)
return base::insert(iterator(pos), value)
iterator erase(const_iterator pos)
return base::erase(iterator(pos))
public: // addons
iterator find (T* key)
return std::find(begin(), end(), key)
const_iterator find (T* key) const
return std::find(begin(), end(), key)
bool contains (T* key) const
return find(key) != end()
T* remove(T* key)
auto it = find(key)
if it == end(); return null
T* val = *it
base::erase(it)
return val
T* add(T* val)
base::push_back(val)
return val
void release()
for T* it : *this; delete it
base::clear()
//########################################################## vset adaptor
template <class T, class K>
struct vset_adaptor
K operator()(T* it) const
return (K)(*it)
bool operator()(K lhs, K rhs) const
return lhs < rhs
template <class T>
struct vset_adaptor<T,T*>
T* operator()(T* it) const
return it
bool operator()(T* lhs, T* rhs) const
return lhs < rhs
//================================================================== vset
template <class T, class K=T*, class F = vset_adaptor<T,K> >
class vset
private:
ptrvect<T> impl
struct Comp
F f
K operator()(T* it) const
return f(it)
bool operator()(K lhs, K rhs) const
return f(lhs, rhs)
bool operator()(T* lhs, K rhs) const
return f(f(lhs), rhs)
bool operator()(K lhs, T* rhs) const
return f(lhs, f(rhs))
bool operator()(T* lhs, T* rhs) const
return f(f(lhs), f(rhs))
Comp comp
public:
typedef typename ptrvect<T>::const_iterator iterator, const_iterator
typedef unsigned size_type
typedef T *value_type
typedef K key_type
typedef typename ptrvect<T>::template condpair<iterator> condpair
public:
iterator begin() const
return iterator(impl.begin())
iterator end() const
return iterator(impl.end())
size_type size() const
return impl.size()
bool empty() const
return impl.empty()
public:
iterator lower_bound(K key) const
return std::lower_bound(impl.begin(), impl.end(), key, comp)
iterator upper_bound(K key) const
return std::upper_bound(impl.begin(), impl.end(), key, comp)
std::pair<iterator, iterator> equal_range(K key) const
return std::equal_range(impl.begin(), impl.end(), key, comp)
iterator find(K key) const
iterator it = lower_bound(key)
return it == end() || comp(key, *it) ? end() : it
bool contains(K key) const
iterator it = lower_bound(key)
return it != end() && !comp(key, *it)
public:
typename std::enable_if<!std::is_same<T*,K>::value,
iterator>::type lower_bound(T* key) const
return std::lower_bound(impl.begin(), impl.end(), comp(key), comp)
typename std::enable_if<!std::is_same<T*,K>::value,
iterator>::type upper_bound(T* key) const
return std::upper_bound(impl.begin(), impl.end(), comp(key), comp)
typename std::enable_if<!std::is_same<T*,K>::value,
std::pair<iterator, iterator> >::type equal_range(T* key) const
return std::equal_range(impl.begin(), impl.end(), comp(key), comp)
typename std::enable_if<!std::is_same<T*,K>::value,
iterator>::type find(T* key) const
iterator it = lower_bound(comp(key))
return it == end() || comp(key, *it) ? end() : it
public:
template<class... Args>
condpair emplace(K key, Args&& ...args)
iterator it = lower_bound(key)
if it == end() || comp(key, *it)
return condpair(impl.insert(it,
new T(key, std::forward<Args>(args)...)), true)
return condpair(it, false)
iterator erase(iterator at)
return impl.erase(at)
public:
T* add(T* value)
iterator it = lower_bound(value)
if it == end() || comp(comp(value), *it)
impl.insert(it, value)
return value
return nullptr
template<class... Args>
T* add(K key, Args&& ...args)
iterator it = lower_bound(key)
if it == end() || comp(key, *it)
T* value = new T(key, std::forward<Args>(args)...)
impl.insert(it, value)
return value
return nullptr
T* get(K key) const
iterator it = find(key)
return it == impl.end() ? nullptr : *it
T* operator[](K key) const
return *emplace(key).first
T* remove(K key)
iterator it = find(key)
if it == impl.end(); return nullptr
T* value = *it
impl.erase(it)
return value
typename std::enable_if<!std::is_same<T*,K>::value,
T*>::type remove(T* key)
return remove(comp(key))
void release()
for T* it : *this
delete it
impl.clear()
void clear()
impl.clear()
You already mentioned c++14 and the template find function. Here is a simple example for who is interested in it:
#include <iostream>
#include <set>
#include <vector>
using namespace std;
class Info
{
int num_;
public:
explicit Info(int n) : num_(n) {}
bool operator<(const Info &other) const { return num_ < other.num_; }
friend inline bool operator<(const Info& lhs, const int& rhs);
friend bool operator<(const int& lhs, const Info& rhs);
};
inline bool operator<(const Info& lhs, const int& rhs) { return lhs.num_ < rhs; }
inline bool operator<(const int& lhs, const Info& rhs) { return lhs < rhs.num_; }
int main()
{
// less<> is a is_transparent comparer
set<Info, less<> > s;
// insert two items
s.insert(Info(2));
s.insert(Info(4));
// search
for (auto n : {1,2,3,4,5}) {
cout << "Searching " << n << (s.find(n) == s.end()?" not found":" found") << endl;
}
return 0;
}
Result:
Searching 1 not found
Searching 2 found
Searching 3 not found
Searching 4 found
Searching 5 not found