Ambiguous overload for operator C++ - c++

#include <iostream>
using namespace std;
class StringNum {
public:
string s;
StringNum() {s = "";}
public:
StringNum(int n) {
for (int i=1; i<=n; i++) s += "x";
}
operator int () {
return s.length();
}
StringNum operator - (StringNum v) {
int len = s.length() - v.s.length();
StringNum res;
for (int i=1;i<=len;i++) res.s += "x";
return res;
}
/* // long solution. But this will allow the program to run.
template <class T>
StringNum operator - (T value) {
return (*this) - StringNum(value);
}
*/
};
int main()
{
StringNum x(4);
cout << 3 - x; // this compiles
cout << x - 3; // error: ambiguous overload for operator -
// change the program so that the 2nd line output 2
return 0;
}
So I have a class that can be upcast from int/downcast to int (this is the simplified version, in the actual version StringNum is HighPrecisionFloat, and int is int/float/double/.. . etc).
When I compile the program, the error message
In function 'int main()':|
error: ambiguous overload for 'operator-' (operand types are 'StringNum' and 'int')|
note: candidate: operator-(int, int) <built-in>|
note: candidate: StringNum StringNum::operator-(StringNum)|
This happens because there are 2 ways to understand x - 3 :
a) int(x) - 3
b) x - StringNum(3)
One way to do this is to use template for each operator (+, -, *, /, dot product, etc...) But that is not very convenient because I have to write templates for each operator.
Is there a better solution to this problem? I wish to call x - StringNum(3). Thank you.

You can make your constructor and conversion to int explicit.
The compiler won't make implicit conversion between those types anymore, but you can still use them like so.
auto stringNum = StringNum{3}; //int to StringNum
int y = static_cast<int>(stringNum);

Related

Using an overloaded operator+ within a function template in C++

This is for a school assignment. I am supposed to adhere to the requirement to use an overloaded operator and it has to be called within the function template called "increase".
This is a class called Inductor.
#pragma once
#include <iostream>
using namespace std;
class Inductor {
friend ostream& operator<<(ostream&, Inductor);
private:
int inductance;
double maxCurrent;
public:
int operator+(int add);
int operator-(int sub);
Inductor(int, double);
};
Inductor::Inductor(int x, double y)
{
inductance = x;
maxCurrent = y;
}
int Inductor::operator+(int add)
{
int newSum = inductance + add;
return newSum;
}
int Inductor::operator-(int sub)
{
int newDiff = inductance - sub;
return newDiff;
}
ostream& operator<<(ostream& out, Inductor inductor)
{
out << "Inductor parameters: " << inductor.inductance << ", " << inductor.maxCurrent << endl;
return out;
}
While this is my function template "increase".
template<class FIRST>
FIRST increase(FIRST a, int b) {
FIRST c;
c = a + b;
return c;
}
Last but not least, my main file:
int main()
{
Inductor ind(450, 0.5);
ind = increase(ind, 70);
}
These are the following compilation errors which I do not understand:
error C2512: 'Inductor': no appropriate default constructor available
error C2679: binary '=': no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
note: could be 'Inductor &Inductor::operator =(Inductor &&)'
note: or 'Inductor &Inductor::operator =(const Inductor &)'
note: see reference to function template instantiation 'FIRST increase<Inductor>(FIRST,int)' being compiled
with
[
FIRST=Inductor
]
note: see declaration of 'Inductor'
Can anyone care to explain why is the compiler throwing these errors? Yes I have googled and searched through StackOverflow, but I do not see an article where an overloaded operator+ from a class is being used within a function template.
template<class FIRST>
FIRST increase(FIRST a, int b) {
FIRST c;
c = a + b;
return c;
}
with FIRST == Inductor has several problems:
FIRST c;: You try to create Inductor whereas there is no default constructor.
c = a + b;: You try to assign to Inductor an int (return type of your operator +), and there is no such operator. and as there is no constructor taking only int to build Inductor, copy assignment is not an alternative.
The first error is easy to fix, just get rid of the variable (return a + b;) or initialize it directly (FIRST c = a + b; return c;).
For the second error, add a (non explicit) constructor taking only an int or change your operator+ to return Inductor directly:
Inductor Inductor::operator+(int add)
{
return Inductor(inductance + add, maxCurrent);
}

Main function of complex number class C++

I am working on an assignment for C++, I am very new to this language. The assignment is about implementing Newton Raphson Method for a function with complex roots. I have implemented the code.
I want to test my code now and I am having difficulty in getting my main function to work properly, there are some concepts I am not understanding that lead to my wrong implementation. I would appreciate some explanations so I can understand better. Thanks.
This is the example of my code:
Complex.h
#include<iostream>
#include<cmath>
using namespace std;
class Complex {
private:
double r;
double i;
public:
Complex(double real, double imaginary);
friend Complex operator+(const Complex& c1, const Complex& c2);
friend ostream& operator<<(ostream& outs, const Complex& number);
};
Complex.cpp
#include "testComplex.h"
Complex::Complex(double real = 0.0, double imaginary = 0.0) : r(real), i(imaginary) {}
Complex operator+(const Complex& c1, const Complex& c2) {
Complex result;
result.r = c1.r + c2.r;
result.i = c1.i + c2.i;
return result;
}
main.cpp
#include <iostream>
#include "testComplex.h"
using namespace std;
int main () {
Complex x;
Complex y;
Complex sum;
x = Complex(2, 4);
y = Complex(3, 0);
sum = x + y;
cout << "The sum (x + y) is: " << sum << endl;
return 0;
}
This is a part of the error that I am receiving:
testComplexmain.cc: In function ‘int main()’:
testComplexmain.cc:8:10: error: no matching function for call to ‘Complex::Complex()’
testComplexmain.cc:8:10: note: candidates are:
testComplex.h:15:2: note: Complex::Complex(double, double)
testComplex.h:15:2: note: candidate expects 2 arguments, 0 provided
testComplex.h:8:7: note: Complex::Complex(const Complex&)
testComplex.h:8:7: note: candidate expects 1 argument, 0 provided
testComplexmain.cc:9:10: error: no matching function for call to ‘Complex::Complex()’
You don't have a default constructor. The two-argument constructor could be used as one, since both arguments are optional; but you'll have to put the default arguments on the declaration in the header, not the definition in the source file, for them to be usable from main.
Personally, I'd use std::complex rather than reinventing it.
You don't have a default constructor because you put the default parameters in the definition, so you can only construct Complex instances by passing two parameters.
You could add a default constructor,
Complex() : r(0), i(0) {}
or put the default parameters in the function declaration instead of in the definition
Complex(double real = 0.0, double imaginary = 0.0);
or write your code like this:
int main () {
Complex x(2, 4);
Complex y(3, 0);
Complex sum = x + y;
cout << "The sum (x + y) is: " << sum << endl;
return 0;
}

strange c++ operator (operator unsigned short())

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;
}

how does operator overload resolution work based on return type in the following code of c++

I know that there is no legal overload based on return type in C++; i.e.
you cannot do something like:
int operator ++ getOwner();
char operator ++ getOwner();
However, I stumbled upon the following:
https://stackoverflow.com/a/9569120/1376317
class Proxy
{
My const* myOwner;
public:
Proxy( My const* owner ) : myOwner( owner ) {}
operator int() const
{
return myOwner->getInt();
}
operator char() const
{
return myOwner->getChar();
}
};
My question is how does operator overload work in this configuration. How do you call this in your main.cpp to get this kind of overloading. How does the compiler deduce , how to call the right overload?
My question is how does operator overload work in this configuration.
These operators provide implicit conversions. That means that this class can be used in many contexts where an int or char is expected, and will use these operators to provide the expected value.
How do you call this in your main.cpp to get this kind of overloading.
Here are a few examples of implicit conversions:
Proxy p = whatever();
int i = p; // convert to int
char c = p; // convert to char
long l = p; // ERROR: ambiguous
void f(int);
f(p); // convert to int
void g(int);
void g(char);
g(p); // ERROR: ambiguous
You can also request explicit conversions using the usual cast notations:
long l = static_cast<int>(p); // convert to int, then to long
g((char)p); // convert to char
How does the compiler deduce , how to call the right overload?
Whenever there's a type mismatch, the compiler looks for a conversion sequence. The rules are quite complicated, but basically the sequence can include at most one user-defined conversion (using either an operator like this, or a converting construction), as well as standard conversions such as int to long.
This is sometimes called the Return Type Resolver idiom or "overload on return type". The conversion operator to call is selected thanks to the context of use where an implicit conversion is needed (for example based on the type of an object to initialize or assign to). For example:
#include <stdio.h>
class RtR {
public:
operator int() const
{
puts("operator int()");
return 42;
}
operator double() const
{
puts("operator double()");
return 3.14;
}
};
void f(int) {}
int main()
{
RtR x;
int i = x; // or int i = RtR();
double d = x;
f(x);
}
output:
operator int()
operator double()
operator int()
See it live.
In 13.1 Overloadable declarations:
Function declarations that differ only in the return type cannot be
overloaded. [ Note: ... It does not apply to sets of functions
fabricated as a result of name lookup (e.g., because of using-directives) or overload resolution (e.g.,
for operator functions) ... ]
Hence this is valid:
struct X {
// Conversion function:
operator int () { return 1; }
operator double () { return 2; }
};
In addition (not relating directly to the question):
struct Y
{
// Operator (Function call):
int operator () (int) { return 1; }
double operator () (double) { return 2; }
// Operator (Subscripting):
int operator [] (int) { return 1; }
double operator [] (double) { return 2; }
// Operator (Shift):
int operator << (int) { return 1; }
double operator << (double) { return 2; }
// and more ...
};
The above code is for operator type conversions and provide an implicit way to cast the Proxy type to int and char.
The compiler "knows" based on the context of the conversion calls, for instance:
Proxy p;
// p_int will be set equal to p.my_owner->getInt()
int p_int = p;
// p_char will be set equal to p.my_owner->getChar()
char p_char = p;
The fact that it's a proxy is irrelevant; the same thing works for any class. Those are conversion operators, and the compiler does select the right version based on how it's used in the calling code.
struct S {
operator int() const { return 1; }
operator double() const { return 2.0; }
};
int main() {
S s;
int i = s;
double d = s;
std::cout << i << ' ' << d << '\n';
return 0;
}

Overloading "+"-operator

I'm trying to overload the + operator in C++, but get the following error:
operators.cpp: In function ‘int main()’:
operators.cpp: 23:17: error: cannot convert ‘Operators’ to ‘int’ in initialization
This is my code:
#include <iostream>
using namespace std;
class Operators{
private:
int num1;
public:
Operators(int num1){
this->num1 = num1;
}
Operators operator+(Operators o){
return Operators(num1 + o.num1);
}
};
int main(){
Operators o1(5);
Operators o2(10);
Operators res = o1 + o2; // EDITED
cout << res;
}
Could you please help me?
I know, in this case it doesn't make sense to overload it, as I could just say 5+10, but I'm just experimenting.
UPDATE
Thanks, I've edited the int.
But now I'm getting the following error:
operators.cpp: In function ‘int main()’:
operators.cpp: 25:10: error: match for ‘operator<<’ in ‘std::cout << res’
[...]
The problem with this line:
int res = o1 + o2;
Is that your overload of operator + returns an object of type Operators. This means that you are trying to initialize an int (res) from a temporary of type Operators (the result of o1 + o2), but there is no user-defined conversion for doing that.
This is why the compiler is issuing an error. You can fix this easily by adding a conversion operator to your Operators class:
operator int () const { return num1; }
UPDATE:
It seems you have updated your question. The second line below is problematic:
Operators res = o1 + o2;
cout << res;
Unless you defined an overload of operator << for your Operators class, the compiler won't know which overload of operator << to pick for streaming your object of type Operators.
To solve the issue, you can:
Define a conversion operator to int, as suggested above
Define an overload of operator << for Operators, as follows:
friend std::ostream& operator << (std::ostream& o, Operators const& op)
{
o << op.num1;
return o;
}
Here is a live example.
As the error message is trying to tell you, o1 + o2 is of type Operators.
You can't assign that to an int
Your operator+ returns an Operators object. You then try and assign this result to int res. YOu have given no way to convert from an Operators object to an int. You could provide a conversion operator to do this:
operator int() {
return num1;
}
This defines a conversion from Operators to int.
You need to write:
int res = o1.getMethod() + o2.getMethod();
where getMethod() is a public method in your class that returns the private integer num1.
Otherwise, you don't have access to it. Try it.
Change int to Operators, and implement your own copy and default constructor.
#include <iostream>
class Operators
{
private:
int num1;
public:
Operators() = default;
Operators(Operators const& op) : num1(op.num1) {}
Operators(int num1)
{
this->num1 = num1;
}
Operators operator+(Operators o)
{
return num1 + o.num1;
}
};
int main()
{
Operators o1(5);
Operators o2(10), res;
res = o1 + o2;
std::cout << res;
}
To make this work further, create an overload of operator<< and print the sum.