Need help on std::sort comparison function

F

fade

Good afternoon,
I need some advice on the following:

I've got a class that has a member
std::vector<CString> m_vFileName and a member CString m_path;
The vector contains a bunch of filenames with no path included
(no C:\...) eg: my_file2.jpg, my_file1.bmp, etc...
and m_path stores the path, eg: C:\folder1

I want to sort this vector according to different criterion, such as
filename(asc, desc), date(asc, desc), size(asc, desc).

To sort the vector by filename I use this comparison function:
bool sortVectorByNameUp(CString s1, CString s2)
{ return (s1.CompareNoCase(s2) <= 0)? true : false; }

the call is std::sort(m_vFileName.begin(), m_vFileName.end(),
sortVectorByNameUp);

To sort this vector by date I need to obtain last access time for every
file, and for that, I need to read m_path :(
I can't pass m_path as a parameter because (I think), sortVectorByNameUp
must be a binary function.

If I make this function a member of my class
eg: bool Cteste8View::sortVectorByNameUp(CString s1, CString s2)

I get compilation errors:
..\teste8View.cpp(478) : error C3867: 'Cteste8View::sortVectorByNameUp':
function call missing argument list; use
'&Cteste8View::sortVectorByNameUp' to create a pointer to member
..\teste8View.cpp(478) : error C2780: 'void std::sort(_RanIt,_RanIt)' :
expects 2 arguments - 3 provided
C:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm
(2751) : see declaration of 'std::sort'

I've tried making the call like this:
std::sort(m_vFileName.begin(), m_vFileName.end(),
&Cteste8View::sortVectorByNameUp);
but it doesn't work either

Is there a way to have access to m_path inside the comparison function,
besides using a global variable as intermediate?
And what is the best way to get size and last access time from a file?

Thanks a lot in advance
 
D

Daniel T.

fade said:
Good afternoon,
I need some advice on the following:

I've got a class that has a member
std::vector<CString> m_vFileName and a member CString m_path;
The vector contains a bunch of filenames with no path included
(no C:\...) eg: my_file2.jpg, my_file1.bmp, etc...
and m_path stores the path, eg: C:\folder1

I want to sort this vector according to different criterion, such as
filename(asc, desc), date(asc, desc), size(asc, desc).

To sort the vector by filename I use this comparison function:
bool sortVectorByNameUp(CString s1, CString s2)
{ return (s1.CompareNoCase(s2) <= 0)? true : false; }

the call is std::sort(m_vFileName.begin(), m_vFileName.end(),
sortVectorByNameUp);

To sort this vector by date I need to obtain last access time for every
file, and for that, I need to read m_path :(
I can't pass m_path as a parameter because (I think), sortVectorByNameUp
must be a binary function.

If I make this function a member of my class
eg: bool Cteste8View::sortVectorByNameUp(CString s1, CString s2)

I get compilation errors:
.\teste8View.cpp(478) : error C3867: 'Cteste8View::sortVectorByNameUp':
function call missing argument list; use
'&Cteste8View::sortVectorByNameUp' to create a pointer to member
.\teste8View.cpp(478) : error C2780: 'void std::sort(_RanIt,_RanIt)' :
expects 2 arguments - 3 provided
C:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm
(2751) : see declaration of 'std::sort'

I've tried making the call like this:
std::sort(m_vFileName.begin(), m_vFileName.end(),
&Cteste8View::sortVectorByNameUp);
but it doesn't work either

Is there a way to have access to m_path inside the comparison function,
besides using a global variable as intermediate?
And what is the best way to get size and last access time from a file?

Thanks a lot in advance

struct SortVectorByDateUp : binary_function< CString, CString, bool >
{
const CString path;
SortVectorByDateUp( const CString& path_ ): path( path_ ) { }
bool operator()( const CString& left, const CString& right ) const
{
// do whatever you need to do here
}
};

// in body of member function

sort( m_vFileName.begin(), m_vFileName.end(),
SortVectorByDateUp( m_path ) );
 
S

Salt_Peter

fade said:
Good afternoon,
I need some advice on the following:

I've got a class that has a member
std::vector<CString> m_vFileName and a member CString m_path;
The vector contains a bunch of filenames with no path included
(no C:\...) eg: my_file2.jpg, my_file1.bmp, etc...
and m_path stores the path, eg: C:\folder1

I want to sort this vector according to different criterion, such as
filename(asc, desc), date(asc, desc), size(asc, desc).

To sort the vector by filename I use this comparison function:
bool sortVectorByNameUp(CString s1, CString s2)
{ return (s1.CompareNoCase(s2) <= 0)? true : false; }

That doesn't sort the vector by filename, it sorts copies which
can/might be modified, not to mention the waste of invoking additional
ctors and d~tors. That statement might sound a little strange for
someone that is doing MFC, or whatever proprietary language you are
using, but thats absolutely fundamental in C++. Comparison parameters
must be const references. Doing otherwise is shooting yourself in the
foot.
Try:
bool sortVectorByNameUp(const CString& s1, const CString& s2)
{
// ...
}

You should both consider and study associative containers (like
std::set or std::map). These sort at insertion and can simply rely on
an operator< overload to order the container. If you decide to go that
route, you'll find out how dangerous it is not to use const references
in this case.
the call is std::sort(m_vFileName.begin(), m_vFileName.end(),
sortVectorByNameUp);

To sort this vector by date I need to obtain last access time for every
file, and for that, I need to read m_path :(
I can't pass m_path as a parameter because (I think), sortVectorByNameUp
must be a binary function.

If I make this function a member of my class
eg: bool Cteste8View::sortVectorByNameUp(CString s1, CString s2)

no, no. Assuming that the vector in question is part of the CTeste8View
class, you don't provide a member function that sorts the vector member
within by passing its elements to an interface of the containing class.
Thats not logical and will obviously fail in an algorithm.
Your vector should be storing Elements of some structure or class, that
class/struct is where the op< or comparator should act upon. One does
not ask an apple tree to compare apples. Trees compare trees and apples
compare apples.
I get compilation errors:
.\teste8View.cpp(478) : error C3867: 'Cteste8View::sortVectorByNameUp':
function call missing argument list; use
'&Cteste8View::sortVectorByNameUp' to create a pointer to member
.\teste8View.cpp(478) : error C2780: 'void std::sort(_RanIt,_RanIt)' :
expects 2 arguments - 3 provided

The error is expected. sort is being asked to act on a Cteste8View
object and yet the iterators are iterating through CStrings.
 
N

Noah Roberts

fade said:
Good afternoon,
I need some advice on the following:

I've got a class that has a member
std::vector<CString> m_vFileName and a member CString m_path;
The vector contains a bunch of filenames with no path included
(no C:\...) eg: my_file2.jpg, my_file1.bmp, etc...
and m_path stores the path, eg: C:\folder1

I want to sort this vector according to different criterion, such as
filename(asc, desc), date(asc, desc), size(asc, desc).

To sort this vector by date I need to obtain last access time for every
file, and for that, I need to read m_path :(
I can't pass m_path as a parameter because (I think), sortVectorByNameUp
must be a binary function.

Make it a functor, an object that has an operator() that takes two
params, or make it a member function and use a binder or boost::bind (I
recommend the later) to tie it to the instance of the object in
question.
I've tried making the call like this:
std::sort(m_vFileName.begin(), m_vFileName.end(),
&Cteste8View::sortVectorByNameUp);

Cteste8View::sortByNameUp()
{
std::sort(begin(), end(), boost::bind(&CTeste8View::sortVByName,
this, _1, _2));
}
 
D

Daniel T.

Salt_Peter said:
That doesn't sort the vector by filename, it sorts copies which
can/might be modified, not to mention the waste of invoking additional
ctors and d~tors. That statement might sound a little strange for
someone that is doing MFC, or whatever proprietary language you are
using, but thats absolutely fundamental in C++. Comparison parameters
must be const references. Doing otherwise is shooting yourself in the
foot.

Your assertion is incorrect. The only thing that the standard requires
of the predicate is that it satisfy the standard mathematical definition
of a strict weak ordering.

The additional c_tors and d_tors that are invoked, might, or might not,
prove to be a performance hit, one can't know without testing.

That said, parameters of 'const T&' and 'T' are logically equivelent and
the former is highly unlikely to be slower than the latter, and for
non-builtin types, is likely to be faster. So I do agree that the OP
should try using 'const T&' instead.
 
F

fade

struct SortVectorByDateUp : binary_function< CString, CString, bool >
{
const CString path;
SortVectorByDateUp( const CString& path_ ): path( path_ ) { }
bool operator()( const CString& left, const CString& right ) const
{
// do whatever you need to do here
}
};

// in body of member function

sort( m_vFileName.begin(), m_vFileName.end(),
SortVectorByDateUp( m_path ) );

Thanks a lot Daniel, Peter and Noah.
Merry Xmas to all.
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top