I’ve got some inherited code that went something like this. (Please hold the laughter… I KNOW this is ugly even after I’ve pseudo-codified it. That’s why I’m trying to improve it and my first thing to work on is the bone headed (by my way of thinking) storing of time as a double of milliseconds since the epoch, and using that time as the key in the multimap). Anyway this is the “before” code, call it foo.h:
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <string>
#include <time.h>
using namespace std;
#include "yasper.h"
using yasper::ptr;
class foo
{
private:
...
public:
foo(...);
virtual ~foo();
...
bool operator() (const ptr<foo> poFoo1, const ptr<foo> poFoo2)
{
...
}
}
...
typedef ptr<foo> fooPtr;
typedef queue<fooPtr> fooQueue;
typedef list<fooPtr> fooList;
typedef fooList *fooListPtr;
typedef multimap<double, fooPtr> fooTimeMap;
I also know that my platform doesn’t provide time precision anywhere near nanoseconds but it is a little better than seconds or milliseconds. Also I’ve tried to understand and implement the suggestions from several similar question both from google results and from this site ( C++ Using .find() with struct as key in map and using struct as key in map ). However those are slightly different because they are for their own new struct and I am trying to do it with an existing standard library struct.
So my main goal is to change that last line to:
typedef multimap<timespec, fooPtr> fooTimeMap;
When I make only that change, I get
In member function ‘bool std::less<_Ty>::operator()(const _Ty&, const _Ty&) const [with _Ty = timespec]’:
/…/include/cpp/xtree:895: instantiated from ‘std::_Tree<_Traits>::iterator std::_Tree<_Traits>::find(const typename _Traits::key_type&) [with _Traits = std::_Tmap_traits, std::less, std::allocator > >, true>]’
/home/…/foo.cpp:109: instantiated from here
/…/include/cpp/functional:136: error: no match for ‘operator<‘ in ‘_Left < _Right’
Based on these and other referenced posts, I’ve tried to define the less than operator for timespec… e.g. before the closing } of class foo, I put
bool operator() (const timespec& lhs, const timespec& rhs)
{
return ( lhs.tv_nsec < rhs.tv_nsec && lhs.tv_sec == rhs.tv_sec ) ||
lhs.tv_sec < rhs.tv_sec;
}
but I guess I don’t understand where is the right place to do that and why. Or even if it is not “the right place” but somewhere that is valid enough to make the multimap<timespec,...> compile (and run : – ). Also some posts talk about defining operator<(…) and others talk about operator()(…).
I’d rather not define a whole new wrapper class like timespec_compare_class around timespec (I’ve seen the syntax of multimap<timespec, fooPtr, timespec_compare_class> in other posts) so I’d rather avoid that if there is a way to do it within class foo itself, or even after the } of foo but still within foo.h.
(note, I don’t think the “bool operator() (const ptr poFoo1, const ptr poFoo2)”, nor the fooQueue, fooList, nor fooListPtr are relevant to the question but I’ve left them in the pseudo-code just in case.)
So, aside from “read a C++ primer”, which I know I need to do, can anyone point me at a slightly quicker solution?
@thb and @MarkRansom, thanks for replying… yeah those were mentioned in other posts too though as I said slightly different cases like with their own new structs, which I tried to apply to my case.
e.g. 1) When I do bool operator() (const timespec& lhs, const timespec& rhs) inside the { braces } of foo, I still get “error: no match for ‘operator<‘ in ‘_Left < _Right'”
e.g. 2) when I do that outside the braces, just before the typedef multimap, I get “bool operator()(const timespec&, const timespec&)’ must be a nonstatic member function”.
e.g. 3) When I do bool operator< (const timespec& lhs, const timespec& rhs) inside the braces, I get “‘bool foo::operator<(const timespec&, const timespec&)’ must take exactly one argument” And even if I changed that to one argument, I don’t think that’s what I want because I’m not trying to tell it how to compare a foo to a timespec.
e.g. 4) When I do that outside the braces, just before the typedef multimap, I get “multiple definition of `operator<(timespec const&, timespec const&)'”.
So are one of these closer to the right track, or something completely different?
I would change it slightly more:
The reason that I would take the extra step is that if you define operator< for timespec is that it has a high chance for a clash with any C++ library that uses time information. They may not define the same ordering and then things get complicated.
By explicitly setting the comparison you guarantee there will be no clashes.