sort / vector

E

eiji

Hi folks,
I have a problem compiling this under VC6!
Maybe someone has some minutes to look at this:

template<class T> class Compare
{
public:
Compare(){};
virtual ~Compare(){};

bool operator()(const T& T1, const T& T2) const
{return T1.GetNumber() < T2.GetNumber();}
};

class Element
{
public:
Element(Model* model, unsigned int number);
virtual ~Element();

unsigned int GetNumber() const { return _number;}
}

std::vector<Element*>* elements = new std::vector<Element*>(0);

elements->push_back(new Element()); // n-times


std::vector<Element*>::const_iterator iterFirst = elements->begin() ;
std::vector<Element*>::const_iterator iterLast = elements->end() ;

std::sort(iterFirst, iterLast, Compare<Element>());

My Compiler tells me(sorry my compiler speaks german, but it is
readable):
error C2664: '()' : Konvertierung des Parameters 1 von 'class
fesolv::Element *' in 'const class fesolv::Element &' nicht moeglich
Ursache: Konvertierung von 'class fesolv::Element *' in 'const
class fesolv::Element' nicht moeglich

I don't know where to start.
Do sort also works for vector<T*>* or only for vector<T*> ????

Thanks,
eiji
 
R

roberts.noah

eiji said:
Hi folks,
I have a problem compiling this under VC6!
Maybe someone has some minutes to look at this:

template<class T> class Compare
{
bool operator()(const T& T1, const T& T2) const
std::vector<Element*>* elements = new std::vector<Element*>(0);
std::sort(iterFirst, iterLast, Compare<Element>());

Notice that your compare function expects references but your vector
contains pointers. The "T" for your compare would want to be Element*
and then of course the body of that operator would need
changing....therefore a seperate ComparePtr functor may be in order.

Keeping pointers in a vector is *generally* a bad move. There are of
course always exceptions to any rule but when you are going to be
keeping pointers in a vector try to find a different way. One way to
do so without all the pita that goes with it is to create a smart
pointer that can be contained in a vector (there are certain rules
about vector contents). I'm not even sure pointers meet those reqs.
 
B

Bob Hairgrove

Hi folks,
I have a problem compiling this under VC6!
Maybe someone has some minutes to look at this:

template<class T> class Compare
{
public:
Compare(){};
virtual ~Compare(){};

The destructor doesn't have to be virtual if you do not inherit any
other types from Compare said:
bool operator()(const T& T1, const T& T2) const
{return T1.GetNumber() < T2.GetNumber();}
};

This won't work for pointers; either you'll need to change this to
accommodate T*, or you will need a second type to deal with them,
e.g.:

bool operator()(const T* T1, const T* T2) const
{return T1->GetNumber() said:
class Element
{
public:
Element(Model* model, unsigned int number);
virtual ~Element();

unsigned int GetNumber() const { return _number;}
}

Some questions/remarks:

(1) Where is _number declared?
(2) You should never use names beginning with an underscore for
anything (see section 17.4.3.1.2 of the C++ for the reason).
(3) If you never want to construct an Element with no arguments, you
should declare a default constructor, but make it private and do not
implement it. This will prevent the compiler from giving you a default
constructor that you don't want.
std::vector<Element*>* elements = new std::vector<Element*>(0);

The default constructor will work fine, no need to pass an argument of
zero:

std::vector said:
elements->push_back(new Element()); // n-times

Hmmm ... I see we have a problem here if you want to hide the default
constructor ... but if you provide initializers/arguments, it's OK.
std::vector<Element*>::const_iterator iterFirst = elements->begin() ;
std::vector<Element*>::const_iterator iterLast = elements->end() ;

std::sort(iterFirst, iterLast, Compare<Element>());

This should work if you (a) pass an object and (b) change the
implementation and signature of Compare<>::eek:perator() to accept T*
instead of T&:

Compare<Element> cmp_obj;
std::sort(iterFirst, iterLast, cmp_obj);

It might also work with Compare<Element>(), but you are creating a
temporary. I don't know why, but I always seem to have trouble when
passing a temporary object to std::sort()...
My Compiler tells me(sorry my compiler speaks german, but it is
readable):
error C2664: '()' : Konvertierung des Parameters 1 von 'class
fesolv::Element *' in 'const class fesolv::Element &' nicht moeglich
Ursache: Konvertierung von 'class fesolv::Element *' in 'const
class fesolv::Element' nicht moeglich

I don't know where to start.
Do sort also works for vector<T*>* or only for vector<T*> ????

Thanks,
eiji

FYI -- übrigens gibt es auch eine deutsche NG für C++-Fragen,
de.comp.lang.iso-c++ ... aber hier bist Du mit Deinen Fragen natürlich
genauso willkommen, wie drüben! :)
 
E

eiji

there are certain rules about vector contents

Nice to know? Any idea where to find them easily?
 
K

Kai-Uwe Bux

eiji said:
Hi folks,
I have a problem compiling this under VC6!
Maybe someone has some minutes to look at this:

template<class T> class Compare
{
public:
Compare(){};
virtual ~Compare(){};

bool operator()(const T& T1, const T& T2) const
{return T1.GetNumber() < T2.GetNumber();}
};

class Element
{
public:
Element(Model* model, unsigned int number);
virtual ~Element();

unsigned int GetNumber() const { return _number;}
}

std::vector<Element*>* elements = new std::vector<Element*>(0);

elements->push_back(new Element()); // n-times


std::vector<Element*>::const_iterator iterFirst = elements->begin() ;
std::vector<Element*>::const_iterator iterLast = elements->end() ;

std::sort(iterFirst, iterLast, Compare<Element>());

My Compiler tells me(sorry my compiler speaks german, but it is
readable):
error C2664: '()' : Konvertierung des Parameters 1 von 'class
fesolv::Element *' in 'const class fesolv::Element &' nicht moeglich
Ursache: Konvertierung von 'class fesolv::Element *' in 'const
class fesolv::Element' nicht moeglich

I don't know where to start.
Do sort also works for vector<T*>* or only for vector<T*> ????

Since your vector has T* elements, your comparison function needs to take T*
as arguments.


Best

Kai-Uwe Bux
 
M

Mike Wahler

eiji said:
Nice to know? Any idea where to find them easily?

Objects to be stored in standard library containers
(e.g. vectors) must be copyable and assignable.

-Mike
 
B

Bob Hairgrove

Keeping pointers in a vector is *generally* a bad move.

Why? People do it all the time. As long as the lifetime of the objects
pointed to is well-managed, there shouldn't be a problem, and it is
the only way to have a container of polymorphic types.
There are of
course always exceptions to any rule but when you are going to be
keeping pointers in a vector try to find a different way. One way to
do so without all the pita that goes with it is to create a smart
pointer that can be contained in a vector (there are certain rules
about vector contents). I'm not even sure pointers meet those reqs.

No need to create a smart pointer that works in containers, it's
already been done by the Boost folks (look for boost::shared_ptr<>):

http://www.boost.org

Beware of std::auto_ptr, however -- that one doesn't work in STL
containers.
 
E

eiji

Thanks a lot.

bool operator()(const T* T1, const T* T2) const
{return T1->GetNumber() < T2->GetNumber();}
and
std::vector<Element*>::iterator iterFirst = elements->begin() ;
std::vector<Element*>::iterator iterLast = elements->end() ;
(no const iterators)
and
Compare<Element> cmp_obj;

works fine!

I didn't put in all code, because the classes are quit big!
(2) You should never use names beginning with an underscore for
anything (see section 17.4.3.1.2 of the C++ for the reason).
Nice to know!
 
B

Bob Hairgrove

Thanks a lot.

bool operator()(const T* T1, const T* T2) const
{return T1->GetNumber() < T2->GetNumber();}
and
std::vector<Element*>::iterator iterFirst = elements->begin() ;
std::vector<Element*>::iterator iterLast = elements->end() ;
(no const iterators)

It should also work with const_iterator, I believe, although Scott
Meyers (among others) recommends to "prefer iterator over
const_iterator" (from an old "C++ Users Journal" article).
 
R

roberts.noah

Bob said:
Why? People do it all the time. As long as the lifetime of the objects
pointed to is well-managed, there shouldn't be a problem,

That IS the problem.

and it is
the only way to have a container of polymorphic types.

Better to wrap in a smart pointer. There are exceptions when you don't
need/want a smart pointer but imo most of the time you should.
Overhead is minimal compared to the time it can save in ownership
issues.
 
B

Bob Hairgrove

Thanks a lot.

bool operator()(const T* T1, const T* T2) const
{return T1->GetNumber() < T2->GetNumber();}
and
std::vector<Element*>::iterator iterFirst = elements->begin() ;
std::vector<Element*>::iterator iterLast = elements->end() ;
(no const iterators)
and
Compare<Element> cmp_obj;

works fine!

I didn't put in all code, because the classes are quit big!
Nice to know!

Duh ... I just realized why you cannot use a const_iterator:
std::sort() needs to reassign the vector elements in order to sort
them!

(Guess I shouldn't post so late at night!)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top