Strange problem with overloading operators

Good time of day!
I have a problem, please, help me to solve it.

Here is code:
types.h:
1
2
3
4
typedef std::map <uint, std::string> ClusterListMapping;

ClusterListMapping& operator+ (ClusterListMapping&, const std::string&);
ClusterListMapping& operator- (ClusterListMapping&, const uint&);

types.cc:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ClusterListMapping& operator+ (ClusterListMapping& list, const std::string& val) {
	list[list.empty() ?  0 : list.rbegin() -> first + 1] = val;
	return list;
}

ClusterListMapping& operator- (ClusterListMapping& list, const uint& key) {
	list.erase(key);
	return list;
}

std::ostream& operator<< (std::ostream& out, UI::ClusterListMapping& list) {
	for(UI::ClusterListMapping::iterator it = list.begin(); it != list.end(); ++it )
		out << it -> first << "\t" << it -> second << "\n";
	return out;
}

It compiled successful, but when I am trying to use operators, like here:
1
2
3
4
5
6
7
8
UI::ClusterListMapping M;

M[0] = "A";
M[1] = "B";
M[2] = "C";
M[3] = "D";

std::cerr << M - 2 << std::endl; // <- here is a problem line 

I am getting strange errors and messages.
1
2
3
4
5
6
CC	main.o : main.cc types.h
main.cc: In function ‘int main(int, char**)’:
main.cc:28: error: no match foroperator-’ in ‘M - 2’
/usr/include/c++/4.4/bits/stl_bvector.h:179: note: candidates are: ptrdiff_t std::operator-(const std::_Bit_iterator_base&, const std::_Bit_iterator_base&)
make: *** [main.o] Error 1
Compilation failed.

Without using operators it works as it should.
Say me please how I should define operators?
Solved by this:
1
2
3
4
5
6
7
8
9
10
	class ClusterListMapping : public std::map <uint, std::string> {
		public:
			ClusterListMapping& operator- (const uint&);
	};


	ClusterListMapping& ClusterListMapping::operator- (const uint& key) {
		(*this).erase(key);
		return (*this);
	}

BUT WHY??? When std::string become a typedefed struct it's working!
Do you really intend operator- to modify the container???

So in other words

1
2
3
4
int x = 4;
int y = 5;
int z = y - x;
//  Now y == 1 ???? 


What is the problem?

Look here, it looks realy nice:
1
2
3
4
5
6
7
8
9
UI::ClusterList L;
L	+ UI::ClusterConfig { "a.cluster.some_host.com", 22, "user", "secret", 9031, 1431, 8, { } }
	+ UI::ClusterConfig { "b.cluster.some_host.com", 22, "user", "secret", 9032, 1432, 4, {0} }
	+ UI::ClusterConfig { "c.cluster.some_host.com", 22, "user", "secret", 9033, 1433, 4, {0} }
	+ UI::ClusterConfig { "d.cluster.some_host.com", 22, "user", "secret", 9034, 1434, 16, {1, 2} };

std::cerr << L << std::endl; // output configuration
std::cerr << ~L << std::endl; // this outputs some value by criteria - used in other cases
std::cerr << !L << std::endl; // outputs an associative array of pairs ID = HOST 

Now, next lines show you, how it should be simple to use the operators:
1
2
3
4
5
6
7
8
UI::ClusterListMapping A = !L - 3;
std::cerr << "A = !L - 3:\n" << A << "\n" << std::endl; // Here we have a mapping on configuration without element ID:0003

UI::ClusterListMapping B = A / L[3].links; // Here we have pairs without pairs, which is int the set {L[3].links}
std::cerr << "B = A / L[3]:\n" << B << "\n" << std::endl;

UI::ClusterListMapping C = !L % L[3].links; // Here we have pairs except of pairs, which not in the set {L[3].links}
std::cerr << "C = A % C[3]:\n" << C << "\n" << std::endl;

This operation is very useful for me and visual optimization of code
I can use a functional analogs but using operators is more shorten and looks very nice
Last edited on
arren wrote:
What is the problem?

What you're doing is one of the reasons some people dislike operator overloading so much. You're ignoring a convention that is second nature to most people. If you insist on overloading an operator, what's wrong with operator-=()?
Last edited on
Ok! I understand your arguments. I forgot a nature of operators and I did it overloading for shortening names of operations...
So you are right guys! But, what will be, if I will do overloading in case of convention?
like here:
1
2
3
4
5
ClusterListMapping& ClusterListMapping::operator- (const uint& key) {
	ClusterListMapping *T = new ClusterListMapping(*this); // here we doing a copy of container
	T -> erase(key); // here we doing some operations
	return (*T); // and as a result, we return a new container with new properties
}

In my previous post in the second piece of code you can see this new operators
Last edited on
So, I decide this is not right way to use operators like I use.
I'll make a functions instead of operators...
Using new is not right in this context, since that would result in a memory leak.
Also, there's no gain in passing small values like an uint by constant reference, copying is fine in this case. Make sure to mark functions that don't modify the object as const, otherwise you won't be able to use them on constant objects and the compiler might not be able to perform some optimizations since it has to assume the function will change the object even if it doesn't.

1
2
3
4
5
ClusterListMapping ClusterListMapping::operator- (uint key) const {
	ClusterListMapping T(*this);
	T-=key; //assuming you already overloaded operator-=
	return T;
}
I agree, memory leak should be, this is because I decide do not overloading operators.
Anyway, I should have a functions that doing modifying the container.
Thanks to all for discussion, may I close it or anyone wants to say something else?
Topic archived. No new replies allowed.