By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,480 Members | 755 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,480 IT Pros & Developers. It's quick & easy.

STL map compare function - can I pass a parameter?

P: n/a
I want to instantiate an STL map with my own compare function, and I
want to pass a parameter to the compare function that will be stored
and used for all comparisons in that map instance.

As an example, let's say the map key is char* strings, and I want the
comparison based on the nth character in the string. When the map is
instantiated, I need to somehow specify n. So I might have something
like this:

class MyClass
{
public:
void MyFunction(int i);

private:
class MyCompare
{
public:
MyCompare() : m_iCharIndex(0) {}
MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}

bool operator()(const char* c1, const char* c2) const
{
return c1[m_iCharIndex] < c2[m_iCharIndex];
}
int m_iCharIndex;
};
};
void MyClass::MyFunction(int i)
{
// this uses default constructor for MyCompare()
std::map<const char*, float, MyCompare> myMap;

// how do I use MyCompare(i) instead?
}
I can create a map with a char* key and MyCompare as the compare
function. But what I want to do is somehow set the m_iCharIndex member
of the MyCompare class for each map that I create (so I might have one
map that keys on the 3rd character of the strings, another that keys on
the 17th character, etc.).

Is there any way that I can do something like this? I'm not actually
trying to implement an nth character compare class. That's just a
concrete example I came up with for illustration purposes. But I am
trying to find a way to pass a parameter to a compare function for each
map that I create. And that parameter will be stored and used in all
comparisons for that map instance.

Any help appreciated.

Apr 19 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Martoon wrote:
I want to instantiate an STL map with my own compare function, and I
want to pass a parameter to the compare function that will be stored
and used for all comparisons in that map instance.

As an example, let's say the map key is char* strings, and I want the
comparison based on the nth character in the string. When the map is
instantiated, I need to somehow specify n. So I might have something
like this:

class MyClass
{
public:
void MyFunction(int i);

private:
class MyCompare
{
public:
MyCompare() : m_iCharIndex(0) {}
MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}
You should probalby merge the two:

MyCompare(int iCharIndex = 0) : m_iCharIndex(iCharIndex) {}

bool operator()(const char* c1, const char* c2) const
{
return c1[m_iCharIndex] < c2[m_iCharIndex];
}
int m_iCharIndex;
};
};
void MyClass::MyFunction(int i)
{
// this uses default constructor for MyCompare()
std::map<const char*, float, MyCompare> myMap;

// how do I use MyCompare(i) instead?
RTFM about 'std::map's constructors.

std::map<const char*, float, MyCompare> myMap(MyCompare(i));
}

[..]


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

P: n/a
Thanks! That's what I was looking for. I'm reading up on the map
constructor.

There's still one point I don't quite follow, though. I can do this:

std::map<const char*, float, MyCompare> myMap(MyCompare(i));

But if I then try to use myMap, it doesn't seem to recongize it as a
map. For example,

bool b = myMap.empty();

yeilds a compiler error "left of '.empty' must have class/struct/union
type". What am I missing here?

Apr 19 '06 #3

P: n/a
Martoon wrote:
Thanks! That's what I was looking for. I'm reading up on the map
constructor.

There's still one point I don't quite follow, though. I can do this:

std::map<const char*, float, MyCompare> myMap(MyCompare(i));

But if I then try to use myMap, it doesn't seem to recongize it as a
map. For example,

bool b = myMap.empty();

yeilds a compiler error "left of '.empty' must have class/struct/union
type". What am I missing here?


My fault! You need the second set of parentheses, otherwise it's
a function declaration:

std::map<const char*, float, MyCompare> myMap((MyCompare(i)));

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

P: n/a
Ahh, thanks! It's all good now.

Apr 19 '06 #5

P: n/a
Martoon wrote:
I want to instantiate an STL map with my own compare function, and I
want to pass a parameter to the compare function that will be stored
and used for all comparisons in that map instance.

As an example, let's say the map key is char* strings, and I want the
comparison based on the nth character in the string. When the map is
instantiated, I need to somehow specify n. So I might have something
like this:

class MyClass
{
public:
void MyFunction(int i);

private:
class MyCompare
{
public:
MyCompare() : m_iCharIndex(0) {}
MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}

bool operator()(const char* c1, const char* c2) const
{
return c1[m_iCharIndex] < c2[m_iCharIndex];
}
int m_iCharIndex;
};
};

[snip]

You have received already advice on how to get this syntactically straight.
However, the code above does no look sound: I have serious doubts that
comparing strings based on their i-th character alone yields a strict weak
ordering for the data types in your application. In other words: your
comparison predicate could cause undefined behavior in std::map.
Best

Kai-Uwe Bux

Apr 19 '06 #6

P: n/a
Kai-Uwe Bux wrote:
Martoon wrote:
I want to instantiate an STL map with my own compare function, and I
want to pass a parameter to the compare function that will be stored
and used for all comparisons in that map instance.

As an example, let's say the map key is char* strings, and I want the
comparison based on the nth character in the string. When the map is
instantiated, I need to somehow specify n. So I might have something
like this:

class MyClass
{
public:
void MyFunction(int i);

private:
class MyCompare
{
public:
MyCompare() : m_iCharIndex(0) {}
MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}

bool operator()(const char* c1, const char* c2) const
{
return c1[m_iCharIndex] < c2[m_iCharIndex];
}
int m_iCharIndex;
};
}; [snip]

You have received already advice on how to get this syntactically straight.
However, the code above does no look sound: I have serious doubts that
comparing strings based on their i-th character alone yields a strict weak
ordering for the data types in your application.


Why do you say so? Assuming that all strings do in fact have an i-th
character, this looks like a valid strict weak ordering.

On the other hand, since a map will not allow multiple keys which
compare equal, it seems that this may not be a very useful structure,
but then only the OP knows what he wants to do with this.

Mark

In other words: your comparison predicate could cause undefined behavior in std::map.
Best

Kai-Uwe Bux

Apr 19 '06 #7

P: n/a
Mark P wrote:
Kai-Uwe Bux wrote:
Martoon wrote:
I want to instantiate an STL map with my own compare function, and I
want to pass a parameter to the compare function that will be stored
and used for all comparisons in that map instance.

As an example, let's say the map key is char* strings, and I want the
comparison based on the nth character in the string. When the map is
instantiated, I need to somehow specify n. So I might have something
like this:

class MyClass
{
public:
void MyFunction(int i);

private:
class MyCompare
{
public:
MyCompare() : m_iCharIndex(0) {}
MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}

bool operator()(const char* c1, const char* c2) const
{
return c1[m_iCharIndex] < c2[m_iCharIndex];
}
int m_iCharIndex;
};
}; [snip]

You have received already advice on how to get this syntactically
straight. However, the code above does no look sound: I have serious
doubts that comparing strings based on their i-th character alone yields
a strict weak ordering for the data types in your application.


Why do you say so? Assuming that all strings do in fact have an i-th
character, this looks like a valid strict weak ordering.


That is why I said "serious doubts" instead of: it will not work.

Also, from a standards point of view, the requirement is that the predicate
defines a strict weak ordering on the *type* for the keys. No restriction
is made that only the values actually used in the map have to be ordered.

On the other hand, since a map will not allow multiple keys which
compare equal, it seems that this may not be a very useful structure,
but then only the OP knows what he wants to do with this.


True, and that is why my post was carefully worded:
your comparison predicate could cause undefined behavior in std::map.

^^^^^

In any case, I just wanted to alert the OP of a potential pitfall in his
code. No claim on my part is made as to whether there will be trouble or
not. All I claim is that the code look somewhat dangerous.
Best

Kai-Uwe Bux
Apr 20 '06 #8

P: n/a
Kai-Uwe Bux wrote:
I have serious doubts that comparing strings based on their i-th
character alone yields a strict weak ordering for the data types
in your application.


Any strict weak ordering of a domain Y is equivalent to a strict weak
ordering of domain X, if there is a deterministic mapping y = f(x).

In this case, the domain of strings Y is ordered by any strict weak
ordering
of optional<char> and the function optional<char> get_n(string s);

HTH,
Michiel Salters

Apr 20 '06 #9

P: n/a
Mi*************@tomtom.com wrote:
Kai-Uwe Bux wrote:
I have serious doubts that comparing strings based on their i-th
character alone yields a strict weak ordering for the data types
in your application.


Any strict weak ordering of a domain Y is equivalent to a strict weak
ordering of domain X, if there is a deterministic mapping y = f(x).

In this case, the domain of strings Y is ordered by any strict weak
ordering
of optional<char> and the function optional<char> get_n(string s);


Oops, my bad. I confused it for a total ordering.
Thanks

Kai-Uwe Bux
Apr 20 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.