Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have the following problem:
suppose that I'm trying to implement my own class MyInt, which is capable of holding large numbers (I know about BigNum implementation - this is just a practice). I have implemented constructors that accept int, unsigned long, unsigned long long etc. - hence my question.
I'm trying to overload the operator +, with the following declaration:
friend MyInt operator+(const MyInt &, const MyInt &);
inside the class.
It works fine when I'm adding to MyInt's, however I would like it to work in cases like
MyInt x(0);
x = x + 1;
When I call it like that, I get the following output:
error: ambiguous overload for ‘operator+’ (operand types are ‘MyInt’ and ‘int’)
I would appreciate any suggestions on how to solve that
Edit:
Here's sample code, written by me. The constructor is explicit
using namespace std;
class MyInt {
public:
MyInt() {};
explicit MyInt(int) {};
friend MyInt operator+(const MyInt &x, const MyInt &y) {
MyInt result;
cout << "operator + " << endl;
return result;
}
};
int main() {
MyInt x;
x = x + x; //this is fine
x = x + 1; //this is not
}
The construct is explicit, means the implicit conversion from int to MyInt is not allowed, and then operator+(const MyInt &, const MyInt &) couldn't be applied for the call of MyInt + int.
Solution1
Add overload version of operator+, such as:
MyInt operator+(const MyInt &, int);
MyInt operator+(int, const MyInt &);
Solution2
Remove explicit from the constructor.
Given the following problem:
using namespace std;
class MyInt {
public:
MyInt() {};
explicit MyInt(int) {};
friend MyInt operator+(const MyInt &x, const MyInt &y) {
MyInt result;
cout << "operator + " << endl;
return result;
}
};
int main() {
MyInt x;
x = x + x; //this is fine
x = x + 1; //this is not
}
… a reasonable solution is to make the converting constructor implicit, i.e. non-explicit.
For example, std::string allows you to construct a std::string implicitly from a literal. That provides a great practical benefit. But then, there is no problem with s + s because there's no built-in + for pointer arguments, and std::string doesn't provide implicit conversion back to char const*.
Still, I think an implicit conversion to the big-number class makes sense. Make the opposite conversion, to built-in type, explicit (if it's implicit then this problem pops up again). And preferably named.
The solution is to add an operator+(const MyInt & lhs, int rhs);
Another solution is to add a MyInt(int) constructor that is then implicitly called by the compiler.
Related
I would like to know how I should define the class my_int so that the cast from int to std::complex< my_int > is done by the compiler instead of manually by me.
The following program does not compile if 4 is not casted to "my_int"
// Example program
#include <iostream>
#include <string>
#include <complex>
struct my_int
{
my_int() : _i(0) {}
my_int(const my_int& mi) : _i(mi._i) {}
my_int(int i) : _i(i) {}
operator int(){return _i;}
int _i;
};
std::ostream& operator<<(std::ostream& os, const my_int& mi)
{
os << mi._i;
return os;
}
int main()
{
std::complex<my_int> ci = 4; // Casting 4 to my_int works
std::cout << ci;
}
I know that if you initialize ci with std::complex<my_int> ci(4) it works, but I want it to work with copy initialization.
You can define you complex class and write the constructor this way.
Complex(int re, int im = 0);
In this case the compiler will implicitly convert int to complex on
Complex c = 5;
The seeming problem is that more than one user-defined conversion is not allowed in the copy-initialization context, and it can be solved by using direct-initialization context, e.g.
std::complex<my_int> ci{4};
However, there is another hidden problem: the effect of instantiating the template complex for any type other than float, double or long double is unspecified, so you have to explicitly specialize it, as StoryTeller pointed out in the comment.
I'm fairly familiar with operator overloading, however I am wondering how do we implement something like this:
myClass myclassobj;
int x;
x = 5;
x = x + myclassobj
There is no way to overload the + operator for the int class, so something should be done from myClass, but how would we do that? I am probably using the wrong keywords, but searching through SO didn't lead to anithing. Apologies if I did something wrong, this is my first post here.
Edit - My class is a custom vector class, so simply converting it to given type won't work.
Define an overloaded operator with the signature int operator+(int, myClass).
You are right.
There is no way to overload the + operator for the int class, so
something should be done from myClass
Your question:
but how would we do that?
My answer:
You should use user defined type conversion. It may work with a conversion operator.
#include <iostream>
class myClass
{
int i;
public:
myClass(int i=0) : i(i) { }
operator int(){ // A conversion from myClass to int may solve your problem.
return i;
}
};
int main()
{
myClass myclassobj(99);
int x=7;
x = 5;
x = x + myclassobj;
std::cout<<x<<std::endl;
return 0;
}
Brian gave a good answer also, but it works only if the overloaded operator does not need protected or private members from the second argument or if overloaded operator declared as friend of myClass.
I run into a strange c++ operator.
http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f0097af7530fe57a100b00d
class Number {
..
operator unsigned short () const;
};
I called this operator as:
a Number(..);
unsigned short b = a.operator unsigned short();
this works, but I can't understand how it works.
first, this operator don't have a return value.
seconds, a.operator unsigned short() is really strange to me. What is a better way to call this?
if I call :
unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?
The function is a user defined conversion operator. More details can be found at http://en.cppreference.com/w/cpp/language/cast_operator.
You said,
this operator don't have a return value. seconds,
The return values of the user define conversion operators is the explicit type. In your case, the return type is unsigned short.
You asked:
What is a better way to call this?
You could do an explicit cast to invoke the function.
Number n;
unsigned short s = (unsigned short)v;
It is also called when an conversion is required by the compiler.
void foo(unsigned short s) {}
Number n;
foo(n); // Number::operator unsigned short() is called to cast
// n to an unsigned short.
You asked:
if I call : unsigned short b = a; does the operator will get called? is there any c++ standard to say about this?
Yes. The user defined operator function gets called.
Here's the relevant sections from the C++ Draft Standard (N3337):
12.3.2 Conversion functions
1 A member function of a class X having no parameters with a name of the form
...
[ Example:
struct X {
operator int();
};
void f(X a) {
int i = int(a);
i = (int)a;
i = a;
}
In all three cases the value assigned will be converted by X::operator int(). — end example ]
This is the conversion operator. A conversion function typically has the general form
operator type() const;
where type represents a type. It means objects of type Number can be converted to short int.
The conversion operator have no explicitly stated return type and no parameters, because the return type is exactly the type in the signature.
It's a conversion function, called to convert your type into a specific other type under various conditions, and it's covered in ISO C++11 12.3.2 Conversion functions.
In your case, it's called when the Number instance needs to be converted into an unsigned short.
By providing conversion operators, you can take full control over what happens during the conversion process, including such evil as the following:
#include <iostream>
struct X {
int val;
X(int v) { val = v; };
operator int() { return val + 1; }; // pure evil
friend std::ostream& operator<< (std::ostream&, X&);
};
std::ostream& operator<< (std::ostream &out, X &x) {
out << x.val;
return out;
}
int main (void) {
X xyzzy (42);;
std::cout << xyzzy << '\n';
std::cout << (int)xyzzy << '\n';
return 0;
}
which will output the value when you use the instance directly, but output something totally different when you cast it.
Now granted, that's rather evil and not a really good use case but you can use this for things such as rounding floats rather than truncating them, when converting to an integer:
#include <iostream>
struct X {
double val;
X(double v) { val = v; };
operator int() { return (int)(val + 0.5); };
friend std::ostream& operator<< (std::ostream&, X&);
};
std::ostream& operator<< (std::ostream &out, X &x) {
out << x.val;
return out;
}
#define E 2.718281828456
int main (void) {
X xyzzy (E);
double plugh = E;
std::cout << plugh << " -> " << (int)plugh << '\n';
std::cout << xyzzy << " -> " << (int)xyzzy << '\n';
return 0;
}
The output of that code is:
2.71828 -> 2
2.71828 -> 3
As a supplement for the first answer, when you use keyword explicit, note the difference, using explicit would force the programmer to assert his intention to convert using a cast:
class Number {
private:
int num;
public:
explicit Number(int number) : num(number) {} // constructor
explicit operator unsigned short () const { // conversion operator
return num;
}
};
int main() {
Number classTypeNumber(10);
// unsigned short convertToUshortNumber = classTypeNumber; // error
// implicit conversion is not allowed.
// now you should explicit convert the instance first.
// typedef unsigned short int __u_short in types.h file.
unsigned short convertToUshortNumber = static_cast<__u_short>(classTypeNumber);
cout << convertToUshortNumber;
}
This question already has answers here:
Overloading by return type
(11 answers)
Closed 8 years ago.
It's possible to overload the same operator twice on C++?
When I try to overload the + operator using the return type as a base, the compiler show me an error.
bigint.h:41:9: error: ‘std::string BigInt::operator+(BigInt)’ cannot be overloaded
bigint.h:40:9: error: with ‘BigInt BigInt::operator+(BigInt)’
This is my code:
.h:
BigInt operator + (BigInt);
string operator + (BigInt);
.cc:
BigInt BigInt::operator + (BigInt M){
if (this->number.size() != M.number.size())
fixLength (this->number, M.number);
// Call Sum;
this->number = Sum (this->number, M.number);
return (*this);
}
string BigInt::operator + (Bigint M){
// Call BigInt overload +;
}
Edit: Apparently I cannot overload the same operator twice using the return type as a base. Suggestions?
As has been pointed out, you cannot overload beased on return type alone. So this is fine:
Foo operator+(const Foo&, const Foo&);
Foo operator+(const char*, double);
but this is not:
Foo operator+(const Foo&, const Foo&);
Bar operator+(const Foo&, const Foo&);
But most of the time there are valid and simple solutions to a given problem. For instance, in a situation like yours, where you want the following to work:
Foo a, b;
Foo c = a + b;
Bar bar = a + b;
then a common strategy is to either give Bar an implicit converting constructor:
struct Bar
{
Bar(const Foo& foo) { .... }
};
or give Foo a conversion operator:
struct Foo
{
explicit operator Bar() { .... }
....
};
Note you can't mark the operator explicit if you don't have a C++11 compiler.
method overload in C++ is by argument list, not the return value.. so in your case, the two methods are ambiguous and the compiler can't tell which one to use (they have the same argument list)
No, you can't overload based on the return type.
From standard docs., Sec 13.1.2,
Function declarations that differ only in the return type cannot be overloaded.
What this means is that methods can be overloading only if they differ by parameters. As with C++, a method's return type is not considered part of the method signature.
Check Wiki for Name Mangling for more details
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I tried to analyse why some of the operators ((), [], ->, =) should be overloaded as member functions only. I failed and I tried to search on internet but of no use. Can any one please help me to understand this restriction?
I think this is most likely why that portion of the standard was written that way.
but if it is not forbidden, the friend version would never be called, in my testing code ,when
Complex operator+(const Complex &other);
is defined as private, the compiler would
give error message
‘Complex Complex::operator+(const Complex&)’ is private
Complex Complex::operator+(const Complex &other)
instead of using the friend version
refer to Why cannot a non-member function be used for overloading the assignment operator?
Because the default operator= provided by the compiler (the memberwise copy one) would always take precedence. I.e. your friend operator= would never be called.
(If the assignment was performed inside a class method, because of the lookup rules, the member function (in this case generated by the compiler) would take precedence)
I try to using operator + for test. it prove the precedence
it outputs:
member function called
7+11i
testing code:
#include<iostream>
using namespace std;
class Complex
{
public:
Complex(int real, int imag);
Complex(void);
~Complex(void);
Complex &Add(const Complex &other);
void Display() const;
Complex operator+(const Complex &other);
friend Complex operator+(const Complex &c1, const Complex &c2);
private:
int real_;
int imag_;
};
Complex::Complex(int real, int imag): imag_(imag), real_(real)
{
}
Complex::Complex(void)
{
}
Complex::~Complex(void)
{
}
Complex &Complex::Add(const Complex &other)
{
real_ += other.real_;
imag_ += other.imag_;
return *this;
}
void Complex::Display() const
{
cout << real_ << "+" << imag_ << "i" << endl;
}
Complex Complex::operator+(const Complex &other)
{
int r = real_ + other.real_;
int i = imag_ + other.imag_;
std::cout << "member function called"<< std::endl;
return Complex(r, i);
}
Complex operator+(const Complex &c1, const Complex &c2)
{
int r = c1.real_ + c2.real_;
int i = c1.imag_ + c2.imag_;
std::cout << "friend function called"<<std::endl;
return Complex(r, i);
}
int main(void)
{
Complex c1(3, 5);
Complex c2(4, 6);
Complex c3 = c1 + c2;
c3.Display();
return 0;
}
Certain forms of operators require access to the "this" pointer of an instance of a class in order to operate directly on that instance as they only take a single argument to the same type.
class A{
public:
int x;
// only takes a reference to another 'A' type, so we need the 'this' pointer
A& operator=(const A& other){
this->x = other.x;
return *this;
}
};
Although maybe not very satisfying, here's what the standard has to say about it:
(emphasis is mine)
§3.5.3 Assignment
An assignment operator shall be implemented by a non-static member function with exactly one parameter.
§3.5.4 Function call
operator() shall be a non-static member function with an arbitrary number of parameters.
§3.5.5 Subscripting
operator[] shall be a non-static member function with exactly one parameter.
§3.5.6 Class member acess
operator-> shall be a non-static member function taking no parameters.
I can't speak to the reasoning behind these requirements, so I will leave that aspect to those that are more familiar with how compilers are designed.