Resolving operator ambiguity - c++

I have the following map type...
std::map<D3DXCOLOR, ID3DXMesh*>
During compilation, xfunctional complains that it cannot resolve an ambiguity regarding the key type;
error C2593: 'operator <' is ambiguous
The candidate operators detected by the compiler are as follows;
built-in C++ operator<(DWORD, DWORD)
built-in C++ operator<(FLOAT, FLOAT)
built-in C++ operator<(D3DCOLORVALUE, D3DCOLORVALUE)
The D3DXCOLOR struct consists of 4 floats r, g, b, and a respectively but does not define a operator <. It does however provide cast functions for DWORD FLOAT and D3DCOLORVALUE, hence the entries in the candidate list.
I am contemplating the best way to resolve this problem. I could write my own inline operator for D3DXCOLOR, wrap the colour inside a new class which provides its own operator <, or is it possible to somehow hint to the compiler which implementation should be chosen from the list of candidates? The DWORD operator < would meet my requirements adequately.

You have three options. Supposing for example that you want them compared as colorvalues:
1) Define operator<:
bool operator<(const D3DXCOLOR &lhs, const D3DXCOLOR &rhs) {
return static_cast<D3DCOLORVALUE>(lhs) < static_cast<D3DCOLORVALUE>(rhs);
}
2) Specialize std::less:
namespace std {
template <>
struct less<D3DXCOLOR> {
bool operator()(const D3DXCOLOR &lhs, const D3DXCOLOR &rhs) {
return static_cast<D3DCOLORVALUE>(lhs) < static_cast<D3DCOLORVALUE>(rhs);
}
};
}
3) Supply a third template parameter to your map - note that this changes the type of the map, so if you pass the map around a lot this might be inconvenient. But it expresses that the ordering is to be used only for this map, not as the canonical "correct" order of colors for any other purpose.
struct mycomparator {
bool operator()(const D3DXCOLOR &lhs, const D3DXCOLOR &rhs) {
return static_cast<D3DCOLORVALUE>(lhs) < static_cast<D3DCOLORVALUE>(rhs);
}
};
std::map<D3DXCOLOR, ID3DXMesh*, mycomparator>

You can just pass a less-than functor to the map class template that should be used.
struct D3DXCOLOR_less {
bool operator ()(D3DXCOLOR const&a, D3DXCOLOR const& b) const { … }
};
std::map<D3DXCOLOR, ID3DXMesh*, D3DXCOLOR_less> foo;
This is definitely what I would do in this case, unless you also need the operator < for this class in other cases.

You'll need to write your own operator<, or provide a comparator functor to the map.
struct CompareColor {
bool operator()(D3DXCOLOR const & L, D3DXCOLOR const & R) const {
// Compare and return whether L is less than R
}
}
map<D3DXCOLOR, ID3DXMesh*, CompareColor> TheMap;

Define operator< function for D3DXCOLOR, as
bool operator<(const D3DXCOLOR &c1, const D3DXCOLOR &c2)
{
return <some boolean value>;
}
Or define a compare functor, something called D3DXCOLOR_LESS and pass it as third parameter to the std::map:
struct D3DXCOLOR_LESS
{
bool operator()(const D3DXCOLOR &c1, const D3DXCOLOR &c2)
{
return <some boolean value>;
}
};
std::map<D3DXCOLOR, ID3DXMesh*, D3DXCOLOR_LESS> colormap;

Actually RGBA color have no some default quasi-order like any scalar. And you shouldn't define one in global context, but you can define your own ordering and specify it in std::map template instance. See parameters description at http://www.sgi.com/tech/stl/Map.html

Related

Comparing struct in c++

Do anyone know a general method to declare a comparision function for struct so that I can use it in sort , priority queue , map ,set ...
I would also know how to specify the comparision function when declaring a data structure (like map ) having a structure as a key (in the case where i have two or more comparision functions)
Thank you in advance
How can the method be "general"?
Let's say you have this struct.
struct MyStruct{
A a; // A is your own class
};
How would the compiler know how to compare objects of type A?
You need to define a comparison operator yourself.
bool operator()(const MyStruct& s1, const MyStruct& s2);
This function can be given as a compare-function when creating for example a std::map.
explicit map (const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
std::map
comp: Binary predicate that, taking two element keys as argument, returns true if the first argument goes before the second argument in the strict weak ordering it defines, and false otherwise.
defaults to
less<key_type>
The comparison function depends from the semantics of your struct. What does it mean that a < b for your type?
In general, a compare function is something along the line of this (references are optional):
bool comp( const YourType& a, const YourType& b );
To make a map use your compare function, you must write like this:
#include <map>
struct YourType{
int v;
};
struct YourTypeComparison{
bool operator()( const YourType& a, const YourType& b ) { return a.v < b.v; }
};
int main()
{
std::map<YourType,int, YourTypeComparison> m;
}
Normally you would use the standard containers like std::map< std::string, int >. But they also have a Comparator type and an Allocator type.
The Comparator used by default is std::less, which looks somewhat like this,
template <class T>
struct less : binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {
return x<y;
}
};
(There are some other already made functors http://en.cppreference.com/w/cpp/utility/functional)
Notice that it compares two objects with <. This means that as a "general method" you only need to implement the operator bool operator< (const X& lhs, const X& rhs){...} to allow your objects to be sorted. See Operator Overloading FAQ. As a rule of thumb, if you're going to implement one comparison operator then you should implement the others too.
If you need to sort your keys in another way you can define your own comparator (functor).
template < class T >
struct myLess {
bool operator()( const T& lhs, const T& rhs ) const {
return lhs < rhs;
}
};
And use it in a map like std::map< int, int, myLess<int> >.
You can also not use templates at all if you only need to compare one type.
struct myLess {
bool operator()( const int& lhs, const int& rhs ) const {
return lhs < rhs;
}
};
Then you only have to write std::map< int, int, myLess >.
Keep in mind that the objects you're comparing are the Key types, not necessarily the Contained types.

Error in operator function in multimap

I am trying to create a multimap using multikey structure as a key and I am getting a error described below:
code:
struct stCont
{
long long Tok;
char Reserved;
long long Asset;
}
struct MultiKey {
char InstrumentName[6];
char Symbol[10];
long long ExpiryDate;
}
struct myComp
{
bool operator() (const MultiKey& lhs, const MultiKey& rhs)
{
if((lhs.ExpiryDate==rhs.ExpiryDate)&&(memcmp(lhs.InstrumentName,rhs.InstrumentName,6))&&(memcmp(lhs.Symbol,rhs.Symbol,10)))
{
return 1;
}
return 0;
}
};
std::multimap<MultiKey, stCont,myComp> cont_map;
error:
expression having type 'const myComp' would lose some const-volatile qualifiers in order to call 'bool myComp::operator ()(const MultiKey &,const MultiKey &)'
you should rewrite the multimap code like this and remove the mycomp structure:
struct MultiKey {
char InstrumentName[6];
char Symbol[10];
long long ExpiryDate;
bool operator< (const MultiKey& lhs)const
{
if((lhs.ExpiryDate==ExpiryDate)&&(memcmp(lhs.InstrumentName,InstrumentName,6))&&(memcmp(lhs.Symbol,Symbol,10)))
{
return true;
}
return false;
}
};
Why don't you just write just write operator < for MultiKey? Or you'll have to change myComp because it isn't what multimap wants anyway (it wants a less-than comparison).
Look at the The C++11 Standard, §23.4.5.1 and the header:
template <class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key, T> > >
class multimap {
public:
// ...
class value_compare {
friend class multimap;
protected:
Compare comp;
value_compare(Compare c) : comp(c) { }
public:
typedef bool result_type;
typedef value_type first_argument_type;
typedef value_type second_argument_type;
bool operator()(const value_type& x, const value_type& y) const {
return comp(x.first, y.first);
}
};
// ...
};
The comparison function as defined by class value_compare is const. Now, I may be misinterpreting the standard, but this definition seems to be invalid if the operator() is non-const in class Compare.
As to why does it work for some people... Perhaps some finer points about instantiation rules prevent this from being an error, or the implementations are not requierd to adhere strictly to the type definitions in the standard; if so, I'd be glad if someone more versed with The Standard could clarify.
To fix the compile error, declare the comparison function to be a const member:
bool operator() (const MultiKey& lhs, const MultiKey& rhs) const
^^^^^
Then you have another problem: the comparator needs to perform a "less than" comparison, but yours does an equality comparison. You want something like
if (lhs.ExpiryDate < rhs.ExpiryDate) return true;
if (lhs.ExpiryDate > rhs.ExpiryDate) return false;
if (memcmp(lhs.InstrumentName,rhs.InstrumentName,6) < 0) return true;
if (memcmp(lhs.InstrumentName,rhs.InstrumentName,6) > 0) return false;
if (memcmp(lhs.SymbolName,rhs.SymbolName,10) < 0) return true;
return false;
You may find it more convenient to overload operator< rather than defining a named comparator type, so that you can use std::multimap<MultiKey, stCont> with the default comparator.

Overloading operator <

I experts, once again while practicing online, i encountered another problem. This is regarding function template. I am able to create the template but i am not sure how to overload appropriate operator. Please advise.
Question
A function template largestOfTree to return the largest of 3 elements of the same parameterised type. To what class can the function template be applied? Write a class trainEngine with fields for name,model,mass. Overload the appropriate operator so the largestOfThree function template can be applied to three trainEngine objects.
So far ?
template<class T>
bool largestOfThree(T t1, T t2, T t3){
if(t1<t2&&t2<t3){
return true;
}else{
return false;
}
}
trainEngine
class trainEngine {
private:
string name;
string model;
string mass;
public:
friend bool operator<(trainEngine const& lhs) {
if (lhs.name<lhs.model&&lhs.model<lhs.mass){
return true;
}
};
A friend operator< is going to be non-member and should thus be binary. Moreover, you forgot the return type. You likely want:
friend bool operator<(trainEngine const& lhs, trainEngine const& rhs) {
// implementation
}
This would go where your operator< declaration is currently.
Here is a list of idiomatic signatures for operator overloads, and a more elaborate explanation of what juanchopanza mentioned in the comments. Note that the non-member operators can be defined within the class body if they are marked as friends. (They are still non-member functions if you do this.)
If you overload operator '<', you should also overload operator '>'
and you have to write return type bool also.
friend bool operator<(trainEngine const& obj1, trainEngine const& obj2)
In fact, it’s convention in most code to prefer the usage of < over > But more generally, always overload the complete set of related operators; in your case, this would probably also be ==, !=, <= and >=.
Let me note that currently your implementation only depends on the right-hand-side (which you call lhs!). It is surely not what you want.
I think you wanted something like this:
bool operator<(trainEngine const& rhs) {
if(name!=rhs.name)
return(name<rhs.name);
if(model!=rhs.model)
return (model<rhs.model);
return (mass<rhs.mass);
}
or the friend version:
//within the class
friend bool operator<(trainEngine const& lhs, trainEngine const& rhs);
//outside the class
bool operator<(trainEngine const& lhs, trainEngine const& rhs) {
if(lhs.name!=rhs.name)
return(lhs.name<rhs.name);
if(lhs.model!=rhs.model)
return (lhs.model<rhs.model);
return (lhs.mass<rhs.mass);
}

C++ How to Sort Vector making use of Template

C++ How to Sort Vector making use of Template
Hi Guys, thanks for looking at my question.
I got a Templates.h file that goes this way..
/* Template Less Than */
template<typename T>
bool lessThan(T a,T b)
{
return a<b;
}
/* Template greater Than */
template<typename T>
bool greaterThan(T a,T b)
{
return a>b;
}
/* Template Equals */
template<typename T>
bool equals(T a,T b)
{
return a==b;
}
Then i got this class
Map2D
About Map2D..
class Map2D
{
protected:
int x;
int y;
public:
Map2D();
Map2D(int,int);
int getX();
int getY();
};
At my main.cpp i got a vector class of Map2D
vector<Map2D> map2d;
So now i need to sort it by X Ascending.. how do i make use of the template file to do a sort on the vector of it X Ascending.. Consider i will need overload another for DESCENDING later..
Normally i will use
sort(map2d.begin(),map2d.end(),sortByX);
and sortByX will be a struct with overload by it () operator.
But the question now is since i got a template that is lesser than and greater than.. how can i make use of it to sort X by ascending and then another X by descending with the template generic function of Templates.H .
Updates:
I think i need to overload the class Map2D operator > , < and ==
but my question is how do i overload it with the help of MyTemplates.h function such as lesserThan , greaterThan, equals
Thanks.
Define a comparator for your class or simpler, a operator<() overload (which you need to do anyway for your templates to work).
First, fix your templates:
template<typename T>
bool lessThan(const T& a, const T& b)
{
return a<b;
}
template<typename T>
bool greaterThan(const T& a, const T& b)
{
return b<a;
}
template<typename T>
bool equals(const T& a, const T& b)
{
return !(a<b || b<a);
}
Next, define an operator<() on your class.
class Map2D
{
protected:
int x;
int y;
public:
Map2D();
Map2D(int,int);
int getX();
int getY();
// this sample sorts on X dominantly, and Y if X is the same
bool operator <(const Map2D& obj) const
{
return (x < obj.x || (x == obj.x && y < obj.y));
};
}
Now just invoke sort:
std::sort(map2d.begin(), map2d.end());
Invoke using your lessThan template as such:
std::sort(map2d.begin(), map2d.end(), lessThan<Map2D>);
Or your greaterThan template:
std::sort(map2d.begin(), map2d.end(), greaterThan<Map2D>);
In C++11 you could write a lambda function to do it.
Using boost, if you want a "one-step on the fly" functor it would have to be something like:
bind( less<int>, bind(&Map2D::getX(),_1), bind(&Map2D::getX(),_2) )
// or your lessThan<int> which already exists in C++ as less<int>
Not sure if that will work exactly. (Will the 2nd and 3rd binds convert properly to placeholders?) Easier to write a very generic functor that combines what you are trying to do, i.e. extract something from your class (a transformation) then pass that into the predicate.
template< typename Trans, typename Pred >
struct Comparator
{
Comparator( Trans t , Pred p ) : trans( t ), pred ( p )
{
}
template< typename T >
bool operator()( T const& t1, T const& t2 ) const
{
return pred( trans(t1), trans(t2) );
}
private:
Trans trans;
Pred pred;
};
template< typename Trans, typename Pred >
Comparator< Trans, Pred > makeComparator( Trans t, Pred p )
{
return Comparator( t, p );
}
// then in your code
std::sort( map2d.begin(), map2d.end(),
makeComparator( boost::bind( &Map2D::getX(), _1 ), lessThan<int> ) );
should work and you've kept Comparator generic.
(Not sure if boost already offers something like this).
There are a few issues with your code:
Class is missing semicolon at the end.
Your comparison templates should return bool instead of a T.
You miss comparison operators inside your class:
bool operator<(const Map2D &m) const {return /* some code here */ }
bool operator>(const Map2D &m) const {return /* some code here */ }
bool operator==(const Map2D &m) const {return /* some code here */ }
or fix your templates to only use operator<() for all the comparisons (which is a common practice BTW).
When you fix above you just use your templates like that:
sort(map2d.begin(),map2d.end(), lessThan<Map2D>);
sort(map2d.begin(),map2d.end(), greaterThan<Map2D>);
BTW, you do not need custom templates to sort your class in such an easy way. Reuse what is already in STL:
sort(map2d.begin(),map2d.end()); // less
sort(map2d.begin(),map2d.end(), std::greater<Map2D>());
You can find those in functional header. You also cannot use operator==() for sorting but it may be useful for unordered containers introduced in C++11.
EDIT: If your sorting algorithms for Map2D class are fixed (what is lessThan does not change with time) than I suggest following my answer. Otherwise if now you want to sort by X and after a few lines by Y than #MikeSeymour answer may be better suited to your needs.
If you are in C++11, you can write something like this:
std::sort(map2d.begin(), map2d.end(), [](const Map2D& a, const Map2D& b) {
return lessThan(a.getX(), b.getX()); } ); // accending
std::sort(map2d.begin(), map2d.end(), [](const Map2D& a, const Map2D& b) {
return greaterThan(a.getX(), b.getX()); }); // decending
Otherwise you have to implement compare functor, i.e
struct compare
{
bool operator () (const Map2D& a, const Map2D& b)
{
return lessThan(a.getX(), b.getX());
}
};
and then
std::sort(map2d.begin(), map2d.end(), compare());
But really it isn't a good style to have lessThan, greaterThan, since you can compare x directly. And if you want some special comparison for Map2D maybe it is better to make these compare functions only for Map2D objects.
Upd: you can also use just function pointer as your comparator, i.e:
bool compare(const Map2D& a, const Map2D& b)
{
return lessThan(a.getX(), b.getX());
}
and then
std::sort(m.begin(), m.end(), compare);
But you may loss some performance (see comments below).
You first need to overload operators <, > and == to use Map2D with your templates:
class Map2D
{
protected:
int x;
int y;
public:
Map2D();
Map2D(int,int);
int getX();
int getY();
bool operator<(const Map2D& other)const //less then
{
return x < other.x;
}
//other operators is same manner
}
After you have done you just use it:
sort(map2d.begin(),map2d.end(),lessThan<Map2D>);
You can't really. You'll need to define functors (either functions, or classes that overload operator() appropriately) to do the particular object-member comparisons you need, and your function templates don't do that. You need something like:
struct compare_x_less {
// NOTE: you'll need to declare `get_X() const` for this to work.
// You should do that anyway.
bool operator()(Map2D const & a, Map2D const & b) {
return a.get_X() < b.get_X();
}
};
// and similarly for `compare_x_greater` and any other comparisons you need
std::sort(map2d.begin(),map2d.end(),compare_x_less());
In C++11, lambdas can save you a bit of typing:
std::sort(map2d.begin(),map2d.end(),[](Map2D const & a, Map2D const & b) {
return a.get_X() < b.get_X();
});
sort(map2d.begin(),map2d.end(),lessThan<map2d>);
Be aware that lessThan is a prediacte function that should return instead of T value of type bool
Some additional explanation:
// usage
/* Some moments to mention: if you omit third argument, default argument less<T> will be used,
which is enough for built-in types, also you can use predicates already defined in STL:
greater<T>, less<T> or you can provide your own predicate */
sort(map2d.begin(),map2d.end(),lessThan<map2d>);
// header file, where we define predicats which we shall provide as argument to algorithm sort
// predicate expected by function sort has to obey the following rules:
// 1. return bool 2. accept 2 parameters
/*2 variants of predicat*/
// 1) operator< is overloaded for class T, so we can use it to compare instances of that class
template<typename T>
bool lessThan(T a,T b)
{
return a < b;
}
/* 2) operator< not overloaded, when we have to get values of class members by which we are going to compare them
this could be done in various ways, for ex. by means of getters();*/
template<typename T>
bool lessThan(T a,T b)
{
return a.getValueOfMember() < b.getValueOfMember();
}
A good way, I don't think it's the best.
You can overload the operator (<) & (!=) in the class. If you only want to sort for X.
And just use sort(map2d.begin(), map2d.end()) for ascending. and sort(map2d.rbegin(), map2d.rend()) for descending .. And that solves your problem.
OR:
You can make 2 functions to compare 1 relevant to x & the other relevant to Y.
As:
int cmpx(const void* A, const void *B){
Map2D a = *(Map2D *)A;
Map2D b = *(Map2D *)B;
if(a.x < b.x) return -1;
if(a.x == b.x) return 0;
return 1;
}
// And use
qsort(map2d.begin(), (int)map2d.size(), sizeof(Map2D), cmpx);
And so for Y.
Not sure if map2d.rbegin() will sort this descedingly or you'll have to do it on your own as well.

What are C++ non-template members as used in the Barton-Nackman trick?

From wikipedia:
// A class template to express an equality comparison interface.
template<typename T> class equal_comparable
{
friend bool operator==(T const &a, T const &b) { return a.equal_to(b); }
friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); }
};
class value_type
// Class value_type wants to have == and !=, so it derives from
// equal_comparable with itself as argument (which is the CRTP).
: private equal_comparable<value_type>
{
public:
bool equal_to(value_type const& rhs) const; // to be defined
};
This is supposed to be the Barton-Nackman, that could achieve compile-time dimensional analysis (checking if some operations applied to variables end up in comparable numbers, like speed comparable to space/time but no acceleration).
Could anyone explain me how, or at least explain me what are the NON-TEMPLATE members?
Thanks
The rules of the language have changed since the pattern was invented, although care was taken not to break it. In other words, as far as I can tell, it still works but for different reasons than it originally did. I don't think I would base an attempt at dimensional analysis on this pattern as I think there are better ways of doing that today.
I also think the example is too trivial to be helpful. As already stated the instantiation of equal_comparable<value_type> causes operator== and operator!= for value_type to appear. Since they are non-members it doesn't matter that the inheritance is private, they're still eligable for selection when resolving a call. It's just hard to see the point in this example. Let's say however, that you add a template parameter to equal_comparable and a few other things:
template<typename U, typename V> class equal_comparable
{
friend bool operator==(U const &a, V const &b) { return a.equal_to(b); }
friend bool operator!=(U const &a, V const &b) { return !a.equal_to(b); }
};
class some_other_type
{
bool equal_to(value_type const& rhs) const;
};
class value_type
: private equal_comparable<value_type>, // value_type comparable to itself
private equal_comparable<some_other_type> // value_type comparable to some_other_type
{
public:
bool equal_to(value_type const& rhs) const;
bool equal_to(some_other_type const& rhs) const;
};
Disclaimer: I have no idea if this is the way it's supposed to be used but I'm reasonably sure that it would work as described.
These are actually nontemplate nonmembers - the comparison operators in the base template - they get used by the ADL for the derived class. A template member would be something like:
class C
{
...
template < typename T > void DoGreatStuff( T t ) { ... }
...
};
The instantiation of equal_comparable<value_type> in value_type class causes the compiler to generate two comparison functions:
friend bool operator==(value_type const &a, value_type const &b) { return a.equal_to(b); }
friend bool operator!=(value_type const &a, value_type const &b) { return !a.equal_to(b); }
These functions are nontemplate since they do not depend on any template parameter, but they are also nonmembers since they are declared as friend.