473,466 Members | 1,613 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Sort a Vector of Pointers to an object, based on objects properties

I am trying to make a simulated directory structure application for a
course.

I am using a Vector to store pointers to my Directory objects (as
subdirectories of the current object).

In my header it looks like this (private section)

vector<Directory*Directories;

In my cpp file in the constructor I have this:

Directories.clear();

To add directories to the Vector I have a function that asks for name
of the directory and checks it for validity etc. then passes it off to
create and store the new subdirectory using this function:

bool Directory::Create(string DN) //pass in directory name
{
Directory *ND = new Directory(this, DN);
Directories.push_back(ND);
NumSubDirs++;

sort(Directories.begin(), Directories.end());

return true;
}
As you can see I am calling the sort function. As you may guess from
the fact that I am posting the sort does not work. I am 99% sure it's
because I need to come up with the correct method of overloading the <
operator and the operator.

When sort is called the values change position, they just aren't sorted
by directory name as requested.

I have the following overloaded operator< and operatorfunctions. (I
am not including the headers) which do NOT do the trick.

bool Directory::operator<(const Directory & D)
{
return D.Name < Name;

}

bool Directory::operator<(const Directory *D)
{
return D->Name < this->Name;
}
/*
operator>
*/
bool Directory::operator>(const Directory & D)
{
return Name D.Name;
}
bool Directory::operator>(const Directory * D)
{
return D->Name Name;
}

I am sure that's the problem, I just don't know how to tell it the
correct thing to do...

Thanks.

Dec 1 '06 #1
22 3142
sa***@murdocks.on.ca wrote:
I am trying to make a simulated directory structure application for a
course.

I am using a Vector to store pointers to my Directory objects (as
subdirectories of the current object).

In my header it looks like this (private section)

vector<Directory*Directories;

In my cpp file in the constructor I have this:

Directories.clear();

To add directories to the Vector I have a function that asks for name
of the directory and checks it for validity etc. then passes it off to
create and store the new subdirectory using this function:

bool Directory::Create(string DN) //pass in directory name
{
Directory *ND = new Directory(this, DN);
Directories.push_back(ND);
NumSubDirs++;

sort(Directories.begin(), Directories.end());

return true;
}
As you can see I am calling the sort function. As you may guess from
the fact that I am posting the sort does not work. I am 99% sure it's
because I need to come up with the correct method of overloading the <
operator and the operator.

When sort is called the values change position, they just aren't
sorted by directory name as requested.

I have the following overloaded operator< and operatorfunctions. (I
am not including the headers) which do NOT do the trick.

bool Directory::operator<(const Directory & D)
{
return D.Name < Name;

}

bool Directory::operator<(const Directory *D)
{
return D->Name < this->Name;
}
/*
operator>
*/
bool Directory::operator>(const Directory & D)
{
return Name D.Name;
}
bool Directory::operator>(const Directory * D)
{
return D->Name Name;
}

I am sure that's the problem, I just don't know how to tell it the
correct thing to do...
The regular 'sort' does not compare the objects behind the pointers.
It just compares the pointers. What you need is a custom comparator
which will dereference the pointers before comparing them. Then
pass an instance of that comparator to 'sort' with 3 arguments.

RTFM about the 'sort' with 3 arguments.

BTW, what book on Standard library are you reading? Does it talk
about custom comparators?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 1 '06 #2

sa***@murdocks.on.ca wrote:
I am trying to make a simulated directory structure application for a
course.

I am using a Vector to store pointers to my Directory objects (as
subdirectories of the current object).

In my header it looks like this (private section)

vector<Directory*Directories;

In my cpp file in the constructor I have this:

Directories.clear();

To add directories to the Vector I have a function that asks for name
of the directory and checks it for validity etc. then passes it off to
create and store the new subdirectory using this function:

bool Directory::Create(string DN) //pass in directory name
Do not pass a std::string by copy. Use a const reference.
Otherwise you'll be invoking the std::string copy ctor needlessly.

bool Directory::Create( const std::string& DN )

Although that really should be in a Directory constructor.
{
Directory *ND = new Directory(this, DN);
Directories.push_back(ND);
NumSubDirs++;

sort(Directories.begin(), Directories.end());

return true;
}
As you can see I am calling the sort function. As you may guess from
the fact that I am posting the sort does not work. I am 99% sure it's
because I need to come up with the correct method of overloading the <
operator and the operator.

When sort is called the values change position, they just aren't sorted
by directory name as requested.

I have the following overloaded operator< and operatorfunctions. (I
am not including the headers) which do NOT do the trick.

bool Directory::operator<(const Directory & D)
{
return D.Name < Name;

}

bool Directory::operator<(const Directory *D)
{
return D->Name < this->Name;
}
/*
operator>
*/
bool Directory::operator>(const Directory & D)
{
return Name D.Name;
}
bool Directory::operator>(const Directory * D)
{
return D->Name Name;
}

I am sure that's the problem, I just don't know how to tell it the
correct thing to do...

Thanks.
// Use a functor to establish comparison test - adjust as needed:

#include <algorithm>

struct DirectorySort
{
bool operator()(const Directory* const& r_left, const Directory*
const& r_right)
{
return r_left->getName() < r_right->getName();
}
};

int main()
{
std::vector< Directory* dirs;
dirs.push_back( new Directory("dir_8") );
dirs.push_back( new Directory("dir_1") );
dirs.push_back( new Directory("dir_5") );

std::sort( dirs.begin(), dirs.end(), DirectorySort() );

// deallocate dirs ...
}

Dec 1 '06 #3

Salt_Peter wrote:
sa***@murdocks.on.ca wrote:

Do not pass a std::string by copy. Use a const reference.
Otherwise you'll be invoking the std::string copy ctor needlessly.
Thanks. I should go back through my code, I am sure there are other
places I did it too.
>
bool Directory::Create( const std::string& DN )

Although that really should be in a Directory constructor.
>
// Use a functor to establish comparison test - adjust as needed:

#include <algorithm>

struct DirectorySort
{
bool operator()(const Directory* const& r_left, const Directory*
const& r_right)
{
return r_left->getName() < r_right->getName();
}
};
I added this code to my header in the Private section:

struct DirectorySort
{
bool operator()(const Directory* const& r_left, const
Directory* const& r_right)
{
return r_left->getName() < r_right->getName();
}
};

I get the following compile time errors:

In member function `bool Directory::DirectorySort::operator()(const
Directory* const&, const Directory* const&)':

passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

I found code similar to this on the net earlier but could never figure
out how to make it work.

Any Ideas?

Dec 1 '06 #4

Victor Bazarov wrote:
sa***@murdocks.on.ca wrote:

RTFM about the 'sort' with 3 arguments.

BTW, what book on Standard library are you reading? Does it talk
about custom comparators?
I have two C++ books. Both make mention of vectors, the second is the
better one but neither goes into much depth (at least not enough for me
to understand).

C++ How to program - Deitel & Deitel
Data Structures and Problem Solving - Mark Allen Weiss

the second book has a fair amount but it is scattered throughout. It's
a good book, but a hard read.
>
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 1 '06 #5

Victor Bazarov wrote:
sa***@murdocks.on.ca wrote:

RTFM about the 'sort' with 3 arguments.

BTW, what book on Standard library are you reading? Does it talk
about custom comparators?
I have two C++ books. Both make mention of vectors, the second is the
better one but neither goes into much depth (at least not enough for me
to understand).

C++ How to program - Deitel & Deitel
Data Structures and Problem Solving - Mark Allen Weiss

the second book has a fair amount but it is scattered throughout. It's
a good book, but a hard read.
>
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 1 '06 #6

sa***@murdocks.on.ca wrote in message
<11*********************@79g2000cws.googlegroups.c om>...
>
Salt_Peter wrote:
>>
// Use a functor to establish comparison test - adjust as needed:
#include <algorithm>
struct DirectorySort{
bool operator()(const Directory* const& r_left, const Directory*
const& r_right){
return r_left->getName() < r_right->getName();
}
};

I added this code to my header in the Private section:
An header does not have a 'Private section'. I'm sure you meant in the class?
>
struct DirectorySort{
bool operator()(const Directory* const& r_left, const
Directory* const& r_right){
return r_left->getName() < r_right->getName();
}
};

I get the following compile time errors:

In member function `bool Directory::DirectorySort::operator()(const
Directory* const&, const Directory* const&)':
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

I found code similar to this on the net earlier but could never figure
out how to make it work.
Any Ideas?
Yeah, but they seem to be bad ideas (non-const).
Shouldn't hurt because you are only returning a bool (nothing anybody could
use to change anything).

struct DirectorySort{
bool operator()( Directory * const r_left,
Directory * const r_right){
return r_left->GetName() < r_right->GetName();
}
};

Did you change Directory::GetName() to Directory::getName()? If so, correct
it in that struct.

--
Bob R
POVrookie
Dec 1 '06 #7

BobR wrote:

I added this code to my header in the Private section:

An header does not have a 'Private section'. I'm sure you meant in the class?
Okay; Nube alert! (me)

In my class .h file in the private section is where I added it.

struct DirectorySort{
bool operator()(const Directory* const& r_left, const
Directory* const& r_right){
return r_left->getName() < r_right->getName();
}
};

I get the following compile time errors:

In member function `bool Directory::DirectorySort::operator()(const
Directory* const&, const Directory* const&)':
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

I found code similar to this on the net earlier but could never figure
out how to make it work.
Any Ideas?

Yeah, but they seem to be bad ideas (non-const).
Shouldn't hurt because you are only returning a bool (nothing anybody could
use to change anything).

struct DirectorySort{
bool operator()( Directory * const r_left,
Directory * const r_right){
return r_left->GetName() < r_right->GetName();
}
};

Did you change Directory::GetName() to Directory::getName()? If so, correct
it in that struct.
I have made certain that the GetName() is case correct and tried your
code but I get the same error:
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers
--
Bob R
POVrookie
Dec 1 '06 #8

sa***@murdocks.on.ca wrote in message ...
>
BobR wrote:
In my class .h file in the private section is where I added it.
>Any Ideas?

Yeah, but they seem to be bad ideas (non-const).
Shouldn't hurt because you are only returning a bool (nothing anybody
could
>use to change anything).

struct DirectorySort{
bool operator()( Directory * const r_left,
Directory * const r_right){
return r_left->GetName() < r_right->GetName();
}
};

Did you change Directory::GetName() to Directory::getName()? If so,
correct
>it in that struct.
I have made certain that the GetName() is case correct and tried your
code but I get the same error:
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

This compiled. I don't have it fully set up yet and no data, so I don't know
if it works properly.

class Directory{
private:
// Prevent assignment and copy-construction:
Directory( Directory const & ); // just this, don't define it.
void operator=( Directory const & );

std::string Name; // Name of the Directory
unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
int Level;
// File *Files; //Pointer to an array of Files
std::vector<Directory*Directories; // vector to pointers to
directories

Directory *Parent; // pointer to this directories parent dir

struct DirectorySort{
bool operator()( Directory * const r_left,
Directory * const r_right){
return (r_left->GetName() < r_right->GetName());
}
}; // struct DirectorySort

public:

Directory();
Directory( Directory *Parent, std::string N);

std::string GetName();

void SortDirTest();

}; //class Directory

std::string Directory::GetName(){
return Name;
}

void Directory::SortDirTest(){
std::sort( Directories.begin(), Directories.end(),
DirectorySort() );
return;
}

--
Bob R
POVrookie
Dec 2 '06 #9


Tested, good.

// --------------------------
// #includes here

class Directory{
private:
// Prevent assignment and copy-construction:
Directory( Directory const & ); // just this, don't define it.
void operator=( Directory const & );
// --------------------------
std::string Name; // Name of the Directory
unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
int Level;
// File *Files; //Pointer to an array of Files
std::vector<Directory*Directories; // vector to pointers to
directories
Directory *Parent; // pointer to this directories parent dir

struct DirectorySort{ // note: changed back to ref. pass.
bool operator()( Directory const * const &r_left,
Directory const * const &r_right)const{
return (r_left->GetName() < r_right->GetName());
}
}; // struct DirectorySort

// struct DirectorySort{ // - alternate (case insensitive) -
// bool operator()( Directory const * const &r_left,
// Directory const * const &r_right)const{
// std::string sL2( ToUpper(r_left->GetName()) ),
// sR2( ToUpper(r_right->GetName()) );
// return (sL2 < sR2);
// }
// std::string ToUpper(std::string S)const{
// for( size_t i(0); i < S.size(); ++i){ S[ i ] =
std::toupper(S[i]);}
// return S;
// }
// }; // struct DirectorySort (case insensitive)
// --------------------------
public:
Directory();
Directory( Directory *Parent, std::string N);
~Directory();
// --------------------------
std::string GetName() const;
void FillVec();
void SortDirTest();
void PrintVec( std::ostream &out)const;
}; //class Directory
// --------------------------

/* Constructors */
Directory::Directory()
: Name(""), NumSubDirs(0),
NumFiles(0), MaxSubDirs(5),
MaxFiles(5), Level(-1), Parent(0){
//Files = new File[MaxFiles];
} //Directory() Ctor

Directory::Directory(Directory *Parent, std::string N)
: Name(N), NumSubDirs(0),
NumFiles(0), MaxSubDirs(5),
MaxFiles(5), Level(-1), Parent(Parent){
//Files = new File[MaxFiles];
} //Directory(Directory*,string) Ctor

Directory::~Directory(){
//delete[] Files;
// vector holds pointers to 'new' objects.
for( size_t i(0); i < Directories.size(); ++i ){
delete Directories.at( i );
}
} // Dtor
// --------------------------
std::string Directory::GetName() const {
return Name;
}
// --------------------------
void Directory::FillVec(){
std::istringstream sis("Don't chase the rainbow"
" looking for the pot of gold, just pick up"
" the diamonds along the way.");
std::string temp;
while( sis>>temp ){
Directories.push_back( new Directory( this, temp ) );
++NumSubDirs;
} // while(sis)
return;
} // FillVec()
// --------------------------
void Directory::PrintVec( std::ostream &out)const{
for( size_t i(0); i < Directories.size(); ++i ){
out<<Directories.at( i )->GetName()<<std::endl;
}
} // PrintVec(ostream)
// --------------------------
void Directory::SortDirTest(){
std::sort( Directories.begin(), Directories.end(),
DirectorySort() );
return;
}
// --------------------------

int main(){
using std::cout; // for NG post
cout<<"\n___ Directory dir(); ___"<<std::endl;
Directory dir;
dir.FillVec();
dir.PrintVec( cout );
cout<<"___ dir.SortDirTest(); ___"<<std::endl;
dir.SortDirTest();
dir.PrintVec( cout );
cout<<"___ Done ___"<<std::endl;
return 0;
} // main()

// - output -
___ Directory dir(); ___
Don't
chase
the
rainbow
looking
for
the
pot
of
gold,
just
pick
up
the
diamonds
along
the
way.
___ dir.SortDirTest(); ___
Don't
along
chase
diamonds
for
gold,
just
looking
of
pick
pot
rainbow
the
the
the
the
up
way.
___ Done ___

--
Bob R
POVrookie
Dec 2 '06 #10
sa***@murdocks.on.ca wrote:
Salt_Peter wrote:
sa***@murdocks.on.ca wrote:

Do not pass a std::string by copy. Use a const reference.
Otherwise you'll be invoking the std::string copy ctor needlessly.

Thanks. I should go back through my code, I am sure there are other
places I did it too.

bool Directory::Create( const std::string& DN )

Although that really should be in a Directory constructor.

// Use a functor to establish comparison test - adjust as needed:

#include <algorithm>

struct DirectorySort
{
bool operator()(const Directory* const& r_left, const Directory*
const& r_right)
{
return r_left->getName() < r_right->getName();
}
};

I added this code to my header in the Private section:

struct DirectorySort
{
bool operator()(const Directory* const& r_left, const
Directory* const& r_right)
{
return r_left->getName() < r_right->getName();
}
};

I get the following compile time errors:

In member function `bool Directory::DirectorySort::operator()(const
Directory* const&, const Directory* const&)':

passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

I found code similar to this on the net earlier but could never figure
out how to make it work.

Any Ideas?
Its often difficult to pin down what is "the right way" and "the wrong
way" of organizing code. The requisites and requirements should dictate
what should go where exactly.
In this case i don't see why a Directory should have as a member
function, a functor that sorts the contents of a container of Directory
*pointers* (even saying it is painful). A pointer to a Directory is a
pointer, not a Directory. So that comparator should not be a member.
Member functions have a this parameter, which is useless here since you
dealing with pointers, not Directories. What you can do is provide a
member operator< for Directories to sort using their names.

As Scott Meyers wrote in Effective C++: prefer non-member functions
where functional extensibility is compromised. The comparator here is a
good example.

I'ld suggest taking that comparator and placing it in a namespace (ie:
utility). Because who knows when you'll be able to reuse again. You
loose that crucial benefit if you make the comparator a member
function. In the code below, note that the comparator is templated and
therefore can be used to compare *any* object using a shared_pointer
that has a get() member.

Next, don't use new/delete. Instead, use a shared_ptr. Why? Because the
added work pays itself back with interest. You no longer have to worry
about having to delete allocations.
Shared_ptr like boost/shred_ptr are simple to use.

#include <boost/shared_ptr.hpp>
int main()
{
boost::shared_ptr< Directory sp_dir( new Directory("string") );
} // the allocation gets zapped here automatically

If you have a container of Directory objects - not pointers, a *member
function* operator< is enough to sort with. I've included a vector of
Directories below to illustrate sorting by op<.
Imagine the code below where the namespace utility and its templated
comparator are kept in a distinct header for reuse (part of a reuseable
universal toolset).

Note: i can forget having to delete anything since thats now done
automatically.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/shared_ptr.hpp>

class Directory {
std::string s;
public:
Directory( const std::string& r_s ) : s( r_s ) { }
~Directory() {
std::cout << "~D()\n";
}
const std::string& get() const {
return s;
}
bool operator<(const Directory& r_dir) const {
return s < r_dir.get();
}
};

namespace utility { // place this utility in a utility.hpp file

template< typename T >
struct sort_by_shared_ptr { // member function get() required

typedef typename boost::shared_ptr< T SP_T;
bool operator() ( const SP_T& r_left, const SP_T& r_right ) {
return r_left->get() < r_right->get();
}

// why not provide a reverse_sort_by_shared_ptr ?
};

} // namespace utility

int main( ) {
// type-define a shared_ptr for Directory
typedef boost::shared_ptr< Directory SP_Dir;
// a container of the above typedef
std::vector< SP_Dir dirs;
dirs.push_back( SP_Dir( new Directory( "dir_8" )) );
dirs.push_back( SP_Dir( new Directory( "dir_5" )) );
dirs.push_back( SP_Dir( new Directory( "dir_1" )) );

// sort using utility's templated comparator
std::sort( dirs.begin(),
dirs.end(),
utility::sort_by_shared_ptr< Directory >() );

typedef std::vector< SP_Dir >::iterator SPDIter;
for ( SPDIter it = dirs.begin(); it != dirs.end(); ++it ) {
std::cout << ( *it )->get() << std::endl;
}

// a container of plain Directories
std::vector< Directory sdir;
sdir.push_back( Directory("dir_8") );
sdir.push_back( Directory("dir_5") );
sdir.push_back( Directory("dir_1") );

std::sort( sdir.begin(), sdir.end() ); // uses member function op<

typedef std::vector< Directory >::iterator DIter;
for ( DIter it = sdir.begin(); it != sdir.end(); ++it ) {
std::cout << ( *it ).get() << std::endl;
}

return 0;
}

Shared_ptrs like boost::shared_ptr have other benefits that i'm not
going to detail here. They are a requirement, in my opinion, to write
better code. Its a win-win situation.

Dec 2 '06 #11

BobR wrote:
Tested, good.

// --------------------------
// #includes here

class Directory{
private:
// Prevent assignment and copy-construction:
Directory( Directory const & ); // just this, don't define it.
void operator=( Directory const & );
// --------------------------
std::string Name; // Name of the Directory
unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
int Level;
// File *Files; //Pointer to an array of Files
std::vector<Directory*Directories; // vector to pointers to
directories
Directory *Parent; // pointer to this directories parent dir

struct DirectorySort{ // note: changed back to ref. pass.
bool operator()( Directory const * const &r_left,
Directory const * const &r_right)const{
return (r_left->GetName() < r_right->GetName());
}
}; // struct DirectorySort

// struct DirectorySort{ // - alternate (case insensitive) -
// bool operator()( Directory const * const &r_left,
// Directory const * const &r_right)const{
// std::string sL2( ToUpper(r_left->GetName()) ),
// sR2( ToUpper(r_right->GetName()) );
// return (sL2 < sR2);
// }
// std::string ToUpper(std::string S)const{
// for( size_t i(0); i < S.size(); ++i){ S[ i ] =
std::toupper(S[i]);}
// return S;
// }
// }; // struct DirectorySort (case insensitive)
// --------------------------
public:
Directory();
Directory( Directory *Parent, std::string N);
~Directory();
// --------------------------
std::string GetName() const;
void FillVec();
void SortDirTest();
void PrintVec( std::ostream &out)const;
}; //class Directory
// --------------------------

/* Constructors */
Directory::Directory()
: Name(""), NumSubDirs(0),
NumFiles(0), MaxSubDirs(5),
MaxFiles(5), Level(-1), Parent(0){
//Files = new File[MaxFiles];
} //Directory() Ctor

Directory::Directory(Directory *Parent, std::string N)
: Name(N), NumSubDirs(0),
NumFiles(0), MaxSubDirs(5),
MaxFiles(5), Level(-1), Parent(Parent){
//Files = new File[MaxFiles];
} //Directory(Directory*,string) Ctor

Directory::~Directory(){
//delete[] Files;
// vector holds pointers to 'new' objects.
for( size_t i(0); i < Directories.size(); ++i ){
delete Directories.at( i );
}
} // Dtor
// --------------------------
std::string Directory::GetName() const {
return Name;
}
// --------------------------
void Directory::FillVec(){
std::istringstream sis("Don't chase the rainbow"
" looking for the pot of gold, just pick up"
" the diamonds along the way.");
std::string temp;
while( sis>>temp ){
Directories.push_back( new Directory( this, temp ) );
++NumSubDirs;
} // while(sis)
return;
} // FillVec()
// --------------------------
void Directory::PrintVec( std::ostream &out)const{
for( size_t i(0); i < Directories.size(); ++i ){
out<<Directories.at( i )->GetName()<<std::endl;
}
} // PrintVec(ostream)
// --------------------------
void Directory::SortDirTest(){
std::sort( Directories.begin(), Directories.end(),
DirectorySort() );
return;
}
// --------------------------

int main(){
using std::cout; // for NG post
cout<<"\n___ Directory dir(); ___"<<std::endl;
Directory dir;
dir.FillVec();
dir.PrintVec( cout );
cout<<"___ dir.SortDirTest(); ___"<<std::endl;
dir.SortDirTest();
dir.PrintVec( cout );
cout<<"___ Done ___"<<std::endl;
return 0;
} // main()

// - output -
___ Directory dir(); ___
Don't
chase
the
rainbow
looking
for
the
pot
of
gold,
just
pick
up
the
diamonds
along
the
way.
___ dir.SortDirTest(); ___
Don't
along
chase
diamonds
for
gold,
just
looking
of
pick
pot
rainbow
the
the
the
the
up
way.
___ Done ___

--
Bob R
POVrookie
Bob;

Thanks for all that. I STILL can't get it to compile. I am using
DEV-C++. I am not allowed to use any extra classes /headers like boost
etc. so I don't.

When I try to compile I still get (for this line:)
return (r_left->GetName() < r_right->GetName())

error:
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

The course I am taking doesn't really introduce your dev environment,
you are just supposed to figure it out on your own. Is it possible I
need to change something (somewhere... somehow) to do with my compile
options??

I've had a number of suggestions like this one (and come up with a few
of my own) but they all seem to come up with the sam kind of error.

Dec 3 '06 #12

Salt_Peter wrote:
sa***@murdocks.on.ca wrote:
Salt_Peter wrote:
sa***@murdocks.on.ca wrote:
>
Do not pass a std::string by copy. Use a const reference.
Otherwise you'll be invoking the std::string copy ctor needlessly.
Thanks. I should go back through my code, I am sure there are other
places I did it too.
>
bool Directory::Create( const std::string& DN )
>
Although that really should be in a Directory constructor.
>
// Use a functor to establish comparison test - adjust as needed:
>
#include <algorithm>
>
struct DirectorySort
{
bool operator()(const Directory* const& r_left, const Directory*
const& r_right)
{
return r_left->getName() < r_right->getName();
}
};
I added this code to my header in the Private section:

struct DirectorySort
{
bool operator()(const Directory* const& r_left, const
Directory* const& r_right)
{
return r_left->getName() < r_right->getName();
}
};

I get the following compile time errors:

In member function `bool Directory::DirectorySort::operator()(const
Directory* const&, const Directory* const&)':

passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

I found code similar to this on the net earlier but could never figure
out how to make it work.

Any Ideas?

Its often difficult to pin down what is "the right way" and "the wrong
way" of organizing code. The requisites and requirements should dictate
what should go where exactly.
In this case i don't see why a Directory should have as a member
function, a functor that sorts the contents of a container of Directory
*pointers* (even saying it is painful). A pointer to a Directory is a
pointer, not a Directory. So that comparator should not be a member.
Member functions have a this parameter, which is useless here since you
dealing with pointers, not Directories. What you can do is provide a
member operator< for Directories to sort using their names.

As Scott Meyers wrote in Effective C++: prefer non-member functions
where functional extensibility is compromised. The comparator here is a
good example.

I'ld suggest taking that comparator and placing it in a namespace (ie:
utility). Because who knows when you'll be able to reuse again. You
loose that crucial benefit if you make the comparator a member
function. In the code below, note that the comparator is templated and
therefore can be used to compare *any* object using a shared_pointer
that has a get() member.

Next, don't use new/delete. Instead, use a shared_ptr. Why? Because the
added work pays itself back with interest. You no longer have to worry
about having to delete allocations.
Shared_ptr like boost/shred_ptr are simple to use.

#include <boost/shared_ptr.hpp>
int main()
{
boost::shared_ptr< Directory sp_dir( new Directory("string") );
} // the allocation gets zapped here automatically

If you have a container of Directory objects - not pointers, a *member
function* operator< is enough to sort with. I've included a vector of
Directories below to illustrate sorting by op<.
Imagine the code below where the namespace utility and its templated
comparator are kept in a distinct header for reuse (part of a reuseable
universal toolset).

Note: i can forget having to delete anything since thats now done
automatically.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/shared_ptr.hpp>

class Directory {
std::string s;
public:
Directory( const std::string& r_s ) : s( r_s ) { }
~Directory() {
std::cout << "~D()\n";
}
const std::string& get() const {
return s;
}
bool operator<(const Directory& r_dir) const {
return s < r_dir.get();
}
};

namespace utility { // place this utility in a utility.hpp file

template< typename T >
struct sort_by_shared_ptr { // member function get() required

typedef typename boost::shared_ptr< T SP_T;
bool operator() ( const SP_T& r_left, const SP_T& r_right ) {
return r_left->get() < r_right->get();
}

// why not provide a reverse_sort_by_shared_ptr ?
};

} // namespace utility

int main( ) {
// type-define a shared_ptr for Directory
typedef boost::shared_ptr< Directory SP_Dir;
// a container of the above typedef
std::vector< SP_Dir dirs;
dirs.push_back( SP_Dir( new Directory( "dir_8" )) );
dirs.push_back( SP_Dir( new Directory( "dir_5" )) );
dirs.push_back( SP_Dir( new Directory( "dir_1" )) );

// sort using utility's templated comparator
std::sort( dirs.begin(),
dirs.end(),
utility::sort_by_shared_ptr< Directory >() );

typedef std::vector< SP_Dir >::iterator SPDIter;
for ( SPDIter it = dirs.begin(); it != dirs.end(); ++it ) {
std::cout << ( *it )->get() << std::endl;
}

// a container of plain Directories
std::vector< Directory sdir;
sdir.push_back( Directory("dir_8") );
sdir.push_back( Directory("dir_5") );
sdir.push_back( Directory("dir_1") );

std::sort( sdir.begin(), sdir.end() ); // uses member function op<

typedef std::vector< Directory >::iterator DIter;
for ( DIter it = sdir.begin(); it != sdir.end(); ++it ) {
std::cout << ( *it ).get() << std::endl;
}

return 0;
}

Shared_ptrs like boost::shared_ptr have other benefits that i'm not
going to detail here. They are a requirement, in my opinion, to write
better code. Its a win-win situation.
Thanks. Unfortunately (I probably should have mentioned it) for this
assignment we are not allowed to use outside classes/templates etc. so
I can't use boost.

I have seen it mentioned in a lot of postings, even the teaching
assistant talks highly of it. I've never used it because (at least for
now... don't know about later) it's off limits.

Thanks again. I will look at the code to see what I can gleen from it
even without boost.

FYI: Currently my assignment works completely except of course my
search for directories requires I read every one in the vector for a
match because I can't sort it.

I haven't given up, but it is at a state where I can at least in good
conscience say it works. It's due first thing on the 4'th Dec 06 so I
may not get this working.

Dec 3 '06 #13

sa***@murdocks.on.ca wrote in message ...
>
BobR wrote:
>Tested, good.
// --------------------------
[snip code, see prior post]
>
Bob;

Thanks for all that. I STILL can't get it to compile. I am using
DEV-C++. I am not allowed to use any extra classes /headers like boost
etc. so I don't.
I am using Dev-C++ v4.9.9.1 MinGW(GCC v3.3.1) (and wxWidgets for my TestBench
prog).
Project-->Project options-->Parameters-->C++: (wxWidgets flags removed)
-fexceptions
-Wall
# -W
#-pedantic

The '#' comments-out the options(when the 'makefile' is built), sometimes
used.
>
When I try to compile I still get (for this line:)
return (r_left->GetName() < r_right->GetName())

error:
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers
** Double check that you have 'const' on 'GetName(): **

class Directory{
private:
// ..........
// --------------------------
std::string Name; // Name of the Directory
// ..........
// --------------------------
struct DirectorySort{ // note: changed back to ref. pass.
bool operator()( Directory const * const &r_left,
Directory const * const &r_right)const{
return (r_left->GetName() < r_right->GetName());
}
}; // struct DirectorySort
// --------------------------
public:
// ..........
// --------------------------
std::string GetName() const; // <<------- const <<------
// ..........
}; //class Directory
// --------------------------
// ..........
// --------------------------
std::string Directory::GetName() const { // <<------- const
return Name;
}
// --------------------------
// --------------------------
void Directory::SortDirTest(){
std::sort( Directories.begin(), Directories.end(),
DirectorySort() ); // <<------ be sure you put the '()'
return;
}
// --------------------------

That was causing the problem with the code Salt_Peter showed.
Note that even though I put the 'const' different, it's *exactly* the same
thing.
(const 'binds' to the thing to it's left (default). If nothing to left, first
thing on right. So:
const int z(9); // human thinking,
int const z(9); // compiler thinking, Both same.
)
>
The course I am taking doesn't really introduce your dev environment,
you are just supposed to figure it out on your own. Is it possible I
need to change something (somewhere... somehow) to do with my compile
options??

I've had a number of suggestions like this one (and come up with a few
of my own) but they all seem to come up with the sam kind of error.
Check that 'const', and come back here. If it's still not compiling, show the
member function definition that uses the std::sort().

(just in case) I noticed you had overloaded some operators in class
Directory. If it's still not compiling, try temporarily commenting those out
(unlikely it's problem, but, let's be sure).

--
Bob R
POVrookie
Dec 3 '06 #14

BobR wrote in message ...
>
(const 'binds' to the thing to it's left (default). If nothing to left,
first
>thing on right. So:
const int z(9); // human thinking,
int const z(9); // compiler thinking, Both same.
)
int I(9);
const int *Iptr(&I);
int const *Iptr2(&I); // int is const, pointer not.

// see where the second 'const' is in the next line?
// If the 'const' defaulted to "bind to right", this line would compile.

// const int const *Iptr3(&I); // duplicate `const'

int const * const Iptr4(&I);
// int const const *Iptr5(&I); // duplicate `const'
Also:

class Directory{
public:
// --------------------------
std::string GetName() const; // <<------- const <<------

// by putting the 'const' there, you are making a promise that the
// function will not change *anything* in the class. 'Directory' is
// being passed as const, and the compiler sees that
// (without the const) 'GetName()' might try to change something
// inside the class object. So, the compiler says, "error:".

}; //class Directory
Just wanted to 'splain a little.
--
Bob R
POVrookie
Dec 3 '06 #15

BobR wrote:
BobR wrote in message ...

(const 'binds' to the thing to it's left (default). If nothing to left,
first
thing on right. So:
const int z(9); // human thinking,
int const z(9); // compiler thinking, Both same.
)

int I(9);
const int *Iptr(&I);
int const *Iptr2(&I); // int is const, pointer not.

// see where the second 'const' is in the next line?
// If the 'const' defaulted to "bind to right", this line would compile.

// const int const *Iptr3(&I); // duplicate `const'

int const * const Iptr4(&I);
// int const const *Iptr5(&I); // duplicate `const'
Also:

class Directory{
public:
// --------------------------
std::string GetName() const; // <<------- const <<------

// by putting the 'const' there, you are making a promise that the
// function will not change *anything* in the class. 'Directory' is
// being passed as const, and the compiler sees that
// (without the const) 'GetName()' might try to change something
// inside the class object. So, the compiler says, "error:".

}; //class Directory
Just wanted to 'splain a little.
--
Bob R
POVrookie
Hurray!! And there was much rejoicing!!!

That was it! I needed that const!

OY! That was painful.

Thank you all for your patience!

Dec 3 '06 #16

sa***@murdocks.on.ca wrote:
BobR wrote:
Tested, good.

// --------------------------
// #includes here

class Directory{
private:
// Prevent assignment and copy-construction:
Directory( Directory const & ); // just this, don't define it.
void operator=( Directory const & );
// --------------------------
std::string Name; // Name of the Directory
unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
int Level;
// File *Files; //Pointer to an array of Files
std::vector<Directory*Directories; // vector to pointers to
directories
Directory *Parent; // pointer to this directories parent dir

struct DirectorySort{ // note: changed back to ref. pass.
bool operator()( Directory const * const &r_left,
Directory const * const &r_right)const{
return (r_left->GetName() < r_right->GetName());
}
}; // struct DirectorySort

// struct DirectorySort{ // - alternate (case insensitive) -
// bool operator()( Directory const * const &r_left,
// Directory const * const &r_right)const{
// std::string sL2( ToUpper(r_left->GetName()) ),
// sR2( ToUpper(r_right->GetName()) );
// return (sL2 < sR2);
// }
// std::string ToUpper(std::string S)const{
// for( size_t i(0); i < S.size(); ++i){ S[ i ] =
std::toupper(S[i]);}
// return S;
// }
// }; // struct DirectorySort (case insensitive)
// --------------------------
public:
Directory();
Directory( Directory *Parent, std::string N);
~Directory();
// --------------------------
std::string GetName() const;
void FillVec();
void SortDirTest();
void PrintVec( std::ostream &out)const;
}; //class Directory
// --------------------------

/* Constructors */
Directory::Directory()
: Name(""), NumSubDirs(0),
NumFiles(0), MaxSubDirs(5),
MaxFiles(5), Level(-1), Parent(0){
//Files = new File[MaxFiles];
} //Directory() Ctor

Directory::Directory(Directory *Parent, std::string N)
: Name(N), NumSubDirs(0),
NumFiles(0), MaxSubDirs(5),
MaxFiles(5), Level(-1), Parent(Parent){
//Files = new File[MaxFiles];
} //Directory(Directory*,string) Ctor

Directory::~Directory(){
//delete[] Files;
// vector holds pointers to 'new' objects.
for( size_t i(0); i < Directories.size(); ++i ){
delete Directories.at( i );
}
} // Dtor
// --------------------------
std::string Directory::GetName() const {
return Name;
}
// --------------------------
void Directory::FillVec(){
std::istringstream sis("Don't chase the rainbow"
" looking for the pot of gold, just pick up"
" the diamonds along the way.");
std::string temp;
while( sis>>temp ){
Directories.push_back( new Directory( this, temp ) );
++NumSubDirs;
} // while(sis)
return;
} // FillVec()
// --------------------------
void Directory::PrintVec( std::ostream &out)const{
for( size_t i(0); i < Directories.size(); ++i ){
out<<Directories.at( i )->GetName()<<std::endl;
}
} // PrintVec(ostream)
// --------------------------
void Directory::SortDirTest(){
std::sort( Directories.begin(), Directories.end(),
DirectorySort() );
return;
}
// --------------------------

int main(){
using std::cout; // for NG post
cout<<"\n___ Directory dir(); ___"<<std::endl;
Directory dir;
dir.FillVec();
dir.PrintVec( cout );
cout<<"___ dir.SortDirTest(); ___"<<std::endl;
dir.SortDirTest();
dir.PrintVec( cout );
cout<<"___ Done ___"<<std::endl;
return 0;
} // main()

// - output -
___ Directory dir(); ___
Don't
chase
the
rainbow
looking
for
the
pot
of
gold,
just
pick
up
the
diamonds
along
the
way.
___ dir.SortDirTest(); ___
Don't
along
chase
diamonds
for
gold,
just
looking
of
pick
pot
rainbow
the
the
the
the
up
way.
___ Done ___

--
Bob R
POVrookie

Bob;

Thanks for all that. I STILL can't get it to compile. I am using
DEV-C++. I am not allowed to use any extra classes /headers like boost
etc. so I don't.

When I try to compile I still get (for this line:)
return (r_left->GetName() < r_right->GetName())

error:
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers
The compiler is telling you that GetName() is discarding a constant
qualifier.
Note that my get() member function is const:
class Directory {
...
public:
...
std::string get() const; // <- const member function, no *this*
};

The function that processes the comparaison and returns
(r_left->GetName() < r_right->GetName()) is a function whith const ptrs
to const Directories. That means that the compiler must absolute
enforce that get() or GetName() does_not_modify_the_object that holds
the std::string. The function must be const is shown above.
>
The course I am taking doesn't really introduce your dev environment,
you are just supposed to figure it out on your own. Is it possible I
need to change something (somewhere... somehow) to do with my compile
options??

I've had a number of suggestions like this one (and come up with a few
of my own) but they all seem to come up with the sam kind of error.
Dec 3 '06 #17

BobR wrote:
sa***@murdocks.on.ca wrote in message ...

BobR wrote:
Tested, good.
// --------------------------
[snip code, see prior post]

Bob;

Thanks for all that. I STILL can't get it to compile. I am using
DEV-C++. I am not allowed to use any extra classes /headers like boost
etc. so I don't.

I am using Dev-C++ v4.9.9.1 MinGW(GCC v3.3.1) (and wxWidgets for my TestBench
prog).
Project-->Project options-->Parameters-->C++: (wxWidgets flags removed)
-fexceptions
-Wall
# -W
#-pedantic

The '#' comments-out the options(when the 'makefile' is built), sometimes
used.

When I try to compile I still get (for this line:)
return (r_left->GetName() < r_right->GetName())

error:
passing `const Directory' as `this' argument of `std::string
Directory::GetName()' discards qualifiers

** Double check that you have 'const' on 'GetName(): **

class Directory{
private:
// ..........
// --------------------------
std::string Name; // Name of the Directory
// ..........
// --------------------------
struct DirectorySort{ // note: changed back to ref. pass.
bool operator()( Directory const * const &r_left,
Directory const * const &r_right)const{
return (r_left->GetName() < r_right->GetName());
}
}; // struct DirectorySort
// --------------------------
public:
// ..........
// --------------------------
std::string GetName() const; // <<------- const <<------
// ..........
}; //class Directory
// --------------------------
// ..........
// --------------------------
std::string Directory::GetName() const { // <<------- const
return Name;
}
// --------------------------
// --------------------------
void Directory::SortDirTest(){
std::sort( Directories.begin(), Directories.end(),
DirectorySort() ); // <<------ be sure you put the '()'
return;
}
// --------------------------

That was causing the problem with the code Salt_Peter showed.
For the record, the accessor i provided is and was constant.
std::string get() const;
Note that even though I put the 'const' different, it's *exactly* the same
thing.
(const 'binds' to the thing to it's left (default). If nothing to left, first
thing on right. So:
const int z(9); // human thinking,
int const z(9); // compiler thinking, Both same.
)

The course I am taking doesn't really introduce your dev environment,
you are just supposed to figure it out on your own. Is it possible I
need to change something (somewhere... somehow) to do with my compile
options??

I've had a number of suggestions like this one (and come up with a few
of my own) but they all seem to come up with the sam kind of error.

Check that 'const', and come back here. If it's still not compiling, show the
member function definition that uses the std::sort().

(just in case) I noticed you had overloaded some operators in class
Directory. If it's still not compiling, try temporarily commenting those out
(unlikely it's problem, but, let's be sure).

--
Bob R
POVrookie
Dec 3 '06 #18

Salt_Peter wrote:
>
For the record, the accessor i provided is and was constant.
std::string get() const;
Dec 4 '06 #19
>
For the record, the accessor i provided is and was constant.
std::string get() const;
sorry; I must have missed that. Although I am learning; there is a LOT
to learn and I miss things in syntax.

Thanks again for all your amazing efforts.

Dec 4 '06 #20

Salt_Peter wrote in message ...
>
BobR wrote:
>** Double check that you have 'const' on 'GetName(): **
// --------------------------
std::string Directory::GetName() const { // <<------- const
return Name;
}
// --------------------------
That was causing the problem with the code Salt_Peter showed.

For the record, the accessor i provided is and was constant.
std::string get() const;
In your boost example you did. In your first post (the progression I was
following), it was unspecified (but, worked fine once the const is applied.).

--
Bob R
POVrookie
Dec 4 '06 #21

sa***@murdocks.on.ca wrote:

For the record, the accessor i provided is and was constant.
std::string get() const;

sorry; I must have missed that. Although I am learning; there is a LOT
to learn and I miss things in syntax.

Thanks again for all your amazing efforts.
You welcome. my pleasure.

Missing the const is ok - don't worry about that.
Whats important is to understand what the compiler is telling you.
Since the Directory parameter passed to the comparator function is a
constant pointer to a constant Directory, the GetName() member function
needs to be const because otherwise the compiler wouldn't be able to
*guarentee* that the Directory parameter(s) will *not* be modified by
GetName().

const == immutable (even by accident)

That compiler is actually quite smart. Its enforcing rules depending on
how you construct the class.

Dec 4 '06 #22

sa***@murdocks.on.ca wrote in message ...
>
Hurray!! And there was much rejoicing!!!

That was it! I needed that const!

OY! That was painful.
Sometimes 'painful' forces memory. Think you'll ever forget 'const' again?
>
Thank you all for your patience!

After all that, I hope you got a decent grade!

--
Bob R
POVrookie
Dec 4 '06 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Mike | last post by:
Hi there, I'm very new to the STL and am struggling a bit with a sort, and would love some help if possible! I have a simple array V of objects of class OBJ that I want to rank in order of...
4
by: SB | last post by:
I have a class called Process with the following... class Process { private: int processID; // 2 digit number starting at 10 int memorySize; // size of memory allocated to each process...
6
by: Der Andere | last post by:
I have an array of pointers (to a class) which I want to have sorted. I have implemented the < operator for the class but I guess STL sort will sort the pointers according to _their_ values (the...
4
by: Johan | last post by:
Hi, Why does my vector not sort. What I understand is you have to overload the < operator, but that does not work. see code below Thanks Johan
3
by: Alan | last post by:
I have some questions about the STL template "vector": - Do I need to do anything (e.g., "delete") to free memory when I`m done with a vector? I just declare it, and I know it allocates memory...
21
by: yeti349 | last post by:
Hi, I'm using the following code to retrieve data from an xml file and populate a javascript array. The data is then displayed in html table form. I would like to then be able to sort by each...
13
by: smp | last post by:
Does anyone know why making a vector of pointers is so much less efficient than a vector of objects? For a simple example: int num = 20; vector<int*v_int_ptr; v_int_ptr.reserve(num); ...
11
by: Jeff Schwab | last post by:
Would std::sort ever compare an object with itself? I'm not talking about two distinct, equal-valued objects, but rather this == &that. The container being sorted is a std::vector. I've never...
10
by: oktayarslan | last post by:
Hi all; I have a problem when inserting an element to a vector. All I want is reading some data from a file and putting them into a vector. But the program is crashing after pushing a data which...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.