Using an overloaded operator+ within a function template in C++ - 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);
}

Related

Ambiguous overload for operator 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);

Trouble combining templates and class function overloading

The code below works fine, printing out 50 as expected. What I am not understanding, however, is why the same program can't be written with a couple slight alterations to this code. The two lines of proposed code are marked Bad code 1 and 2. When these are substituted for the current working code to the left of them (i.e. in addStuff and main), I get the following error:
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream}' and 'MyClass')|
The way I expected it to work was: when addStuff(x,y) gets called in the (bad) cout line of main(), it first evaluates x+y, the behavior of which is defined by the operator+ MyClass overloaded member function. This should just return a MyClass object, which then has no trouble calling getVar.
What am I missing here?
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass(){}
MyClass(int a) : priV(a){}
MyClass operator+(MyClass otherMC)
{
MyClass newMC;
newMC.priV = this->priV + otherMC.priV;
return newMC;
}
int getVar(){return priV;}
void setVar(int v){priV=v;}
private:
int priV;
};
template <class gen>
gen addStuff(gen x, gen y)
{
return x+y; //Bad code 1: return (x+y).getVar();
}
int main()
{
MyClass x(20), y(30);
cout << addStuff(x,y).getVar() << endl; //Bad code 2: cout << addStuff(x,y) << endl;
}
Your interpretation of what should happen in line 1, return (x+y).getVar(); is correct. The overloaded operator+ will get called on the arguments x and y, and getVar() will be called on the result of operator+. When x and y are of type MyClass, the operator+ call returns an object of type MyClass, so the call to getVar() works.
However, getVar() returns an int. Your function addStuff is specified to return gen, which is the same template parameter that matches the arguments x and y. This means that when x and y are MyClass, the addStuff function must return MyClass.
Thus, when you put addStuff(x,y) in your cout statement, the return type of addStuff is inferred to be MyClass. This is what makes your compiler produce the error that "there is no operator<< for type MyClass."
If you want addStuff to return the result of getVar(), you should declare it to return int, not gen.
Problem is in addStuff function, it returns MyClass object, constructed from int variable. You need to modify this function to work with "bad code"
template <class gen>
int addStuff(gen x, gen y)
{
return (x+y).getVar();
}
Or write an ostream operator for MyClass. For this you need to modify getVar method, include a friend declaration and implement it
int getVar() const { return priV; }
friend std::ostream& operator<< (std::ostream &out, const MyClass& m);
std::ostream& operator<< (std::ostream& out, const MyClass& m) {
out << m.getVar();
return out;
}
This way you don't need to modify addStuff function.
Side note, your code didn't compile for me because there was no default constructor in MyClass, had to modify constructor like this
MyClass(int a = 0) : priV(a) {}
You have to modify addStuff so that it returns an int, not the template parameter gen (which will be MyClass):
template <class gen>
int addStuff (gen x, gen y)
{
return (x + y).getVar ();
}
If you don't change gen into int, then the function will work fine because the constructor MyClass(int a) will be called explicitly and then the result will be an object of type MyClass.
And obviously the compiler will say that you cannot 'cout' an object of type MyClass.
So i suggest you to mark the constructor with explicit:
Also your code didn't compile because there is no default constructor, so add one, or simply mark the parameter with a default value:
explicit MyClass (int a = 0) : priV (a) {}
EDIT:
If you don't want to change the return type of the function if you change the type of the member, you can use decltype, to make the code more generic:
template <class gen>
decltype (auto) addStuff (gen x, gen y) //Or decltype (declval<gen> ().getVar ())
{
return (x + y).getVar ();
}

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

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.