C++ Templates for classes - c++

in this code I tried to make a template for my class, and also 2 template functions, one for standard types and one for my template class, but I wanted to see if I can make a template in a template to get a defined function (I don't know if this was the right way to make it). Finally, after I run the code it gives me some weird errors, like syntax errors etc. Thx for help!
#include <iostream>
template <typename T>
class Complex
{
T _re, _im;
public:
Complex(T re = 0, T im = 0) :_re{re}, _im{im} {};
~Complex() {}
Complex<T>& operator=(const Complex<T>& compl) { if (this == &compl) return *this; this._re = compl._re; this._im = compl._im; return *this; }
Complex<T> operator+(const Complex<T>& compl) { Complex<T> temp; temp._re = _re + compl._re; temp._im = _im + compl._im; return temp}
friend std::ostream& operator<<(std::ostream& os, const Complex<T>& compl) { os << compl._re << " * i " << compl._im; return os; }
};
template <typename T>
T suma(T a, T b)
{
return a + b;
}
template <template<typename> typename T, typename U>
void suma(T<U> a, T<U> b)
{
T<U> temp;
temp = a + b;
std::cout << temp;
}
int main()
{
int a1{ 1 }, b1{ 3 };
std::cout << "Suma de int : " << suma<int>(a1, b1) << std::endl;
double a2{ 2.1 }, b2{ 5.9 };
std::cout << "Suma de double: " << suma<double>(a2, b2) << std::endl;
Complex<int> c1(3, 5), c2(8, 9);
std::cout << "Suma comple int: ";
suma<Complex, int>(c1, c2);
return 0;
}

compl is a c++ keyword (as an alternative for unary operator ~). You used compl as your operator overload parameters.
I didn't know this just a few minutes ago. How did I find out? I pasted your code into godbolt.org and it highlighted the words "compl" as if they were keywords. One Internet search later, they are indeed keywords.
There's also the use of this._re = ... and this._im = ... which doesn't work since this is a pointer and not a reference, so it should be this->_re = ... or preferably, just _re = ....

Your have 3 errors in your program.
First instead of using the keyword compl you could use some other name like i did here.
Second, you were missing a ; after a statement return temp which is fixed in the above code link.
Third you were using
this._re = rhs._re;
this._im = rhs._im;
while the correct way to write this would be:
_re = rhs._re;//note the removed this.
_im = rhs._im;//note the removed this.
After correcting these errors the program works as can be seen here.

Related

Return type deduction failure in overloaded operator

So I have this class template with a single attribute value of type T where I try to overload the + operator, s.t. adding two objects of this class results in another object of this class where the value is the sum of the values of the two. Here's the code:
template<typename T>
class Number
{
public:
//constructors
Number(T value)
: value(value) {}
//attributes
const T value;
//operators
//addition +
template<typename U>
auto operator+(Number<U> other)
{
auto val = this->value + other.value;
Number output(val); //instantiating object of class Number, using constructor
std::cout << "output value: "<<output.value << std::endl;
std::cout << "auto val: "<< val << std::endl;
return output;
}
};
int main()
{
Number<int> x(2);
Number<float> y(2.5);
Number z=x+y;
std::cout << "x = " << x.value << std::endl;
std::cout << "y = " << y.value << std::endl;
std::cout << "x+y = " << z.value << std::endl;
return 0;
}
.
The output is:
output value:4
auto val: 4.5
x = 2
y = 2.5
x+y = 4
.
Obviously there occurs and undesired type conversion, from float to int and I am trying to find out how to avoid this without resorting to specialization. Explicit declaration of the operator output type does not compile. I understand that here the failure lies in that the auto type output becomes the type Number<T>, which in this case is Number<int> but does it have to be int even when a new object is instantiated within the operator definition scope { }?
I'd appreciate some help in this simple exercise, thank you in advance!
As #NathanPierson mentioned:
Number refers to Number<T> inside the operator. You unfortunately cannot use template argument deduction here.
The return type can be determined based on the type of the additon though. You could use a trailing return type to specify the return type. This assumes you don't need to use the result before returning from the function.
class Number
{
public:
...
template<typename U>
auto operator+(Number<U> other) -> Number<decltype(other.value + value)>
{
return {value + other.value};
}
};
.
You could also implement the operator in namespace scope:
template<class T, class U>
auto operator+(Number<T> const& s1, Number<U> const& s2)
{
auto val = s1.value + s2.value;
Number result(val);
return result;
}

Narrowing down a C++ concept to exclude certain types

Suppose I would want to overload the left shift operator for ostreams and all containers.
This is what I'm currently have (compile with -fconcepts):
#include <vector>
#include <iostream>
template<typename Container>
concept bool Iterable = requires(Container t) {
{ *t.begin()++, t.end() };
};
template<Iterable T>
std::ostream& operator<<(std::ostream& out, const T& t) {
for(const auto& it: t) {
out << it << " " ;
}
return out;
}
int main() {
std::vector<int> a = {1, 2, 3};
std::cout << a << std::endl;
std::string str = "something";
// std::cout << str << std::endl; // compile error if the template is defined
return 0;
}
The problem however, is that this there is already a version of the ostream&<< for std::string.
Is there a general (something like a requires not expression) or specific (maybe similar to partial specialization by which I can exclude concrete classes) way to exclude something in a concept?
If not, what is the correct way around this?
template<Iterable T>
requires !requires(std::ostream o, T a) { operator<<(o, a); }
std::ostream& operator<<(std::ostream& out, const T& t) {
for(const auto& it: t) {
out << it << " " ;
}
return out;
}
Add a requirement that the type does not already have an operator<< defined. I am not 100% sure this should work, but it does work on gcc.
(simply o << a crashes gcc)

Function template with operator overloading

I am learning templates and came across function templates.I have developed the following code out of my creativity or just curiosity.
#include<iostream>
using namespace std;
template <typename type>
type Max(type a, type b)
{
return a > b ? a : b;
}
class Foo
{
public:
string s1;
/*
Foo& operator>(Foo &obj)
{
if (this->s1.length() > obj.s1.length() ? true : false)
return *this;
return obj;
}*/
};
int main()
{
cout << Max(2, 3) << endl;
cout << Max(2.0, 3.0) << endl;
Foo a, b;
a.s1 = "AB";
b.s1 = "ABC";
//cout<<Max(a, b).s1;
}
My idea is to pass Foo objects a and b using the Max function template and overload the '>' operator and print the object's string with greater length.
Am i on the right path?Or should it be related to class templates?
You're on the right path, except that the > operator should take a const reference parameter, itself be a const class method, and return a bool:
bool operator>(const Foo &obj) const;
After all, what do you expect the result of > to be, with anything else, for example:
double a, b;
// ...
auto whatisthis= a > b;
Do you expect whatisthis to be a double? Of course not, it will be a bool. The result of any comparison operator, not only > should be a bool. It doesn't really have to be, you can overload the > operator and have it return anything; but that means that you couldn't use the way you expect to use it.
Let operator> return bool, otherwise it can't work with return a > b ? a : b;.
bool operator>(const Foo &obj)
{
return this->s1.length() > obj.s1.length();
}
BTW1: if (this->s1.length() > obj.s1.length() ? true : false) is redundant.
BTW2: It's better to make the parameter type to const since obj won't and needn't be modified.
The answer to your question is "Yes, you're on the right track."
The problem with generic functions is using them efficiently. Your Max() function works, but it copies Objects all over the place.
template <typename type>
const type &Max(const type &a, const type &b)
{
return a > b ? a : b;
}
This solves the Object copying problem - but now it's less efficient for things like ints.
#include <iostream>
using namespace std;
template <typename type>
type Max(type a, type b)
{
return a > b ? a : b;
}
class Foo {
public:
string s1;
bool operator > (Foo &obj) {
return this->s1.length() > obj.s1.length();
}
};
int main()
{
cout << Max(2, 3) << endl;
cout << Max(2.0, 3.0) << endl;
Foo a, b;
a.s1 = "AB";
b.s1 = "ABC";
cout << Max(a, b).s1;
}
This maybe what you want:

Explicit Instantiation of Templated Overloaded Operator

The following code works:
struct A
{
int v = 3;
};
namespace Foo
{
template <int k=11>
int operator+(A const& lhs, A const& rhs)
{
return lhs.v + rhs.v + k;
}
}
using Foo::operator+;
int main()
{
A a1, a2;
std::cout << a1 + a2 << std::endl;
return 0;
}
The using Foo::operator+; directive brings Foo::operator+ into the external lookup scope and the when operator+ is used in the cout call, the default template value of 11 is taken and the result is, as expected: 17 (=3+3+11).
My question is how to change the using clause to explicitly instantiate the operator+ function with a non-default template value?
The line using Foo::operator+<42> does not work.
This is due to ISO C++ Standard 7.3.3.5: A using-declaration shall not name a template-id.
Is there a way around this?
Answering myself...
The problem seems to stem from ISO C++ Standard 7.3.3.5:
A using-declaration shall not name a template-id.
This prevents the acceptance of: using Foo::operator+<42>.
As a work-around I found the following solution that does what I need, at the cost of an extra namespace redirection. The code may still need some massaging but it does get the task done with minimal duplication on the user's side.
See a working version here.
struct A
{
int v = 0;
};
template <int k>
struct Bar
{
static int plus(A const& lhs, A const& rhs)
{
return rhs.v + lhs.v + k;
}
};
namespace Boo
{
using Baz = Bar<42>; // same as `typedef Bar<42> Baz;`
//#include "foo_operators.h"
namespace Foo
{
int operator+(A const& rhs, A const& lhs)
{
return Baz::plus(lhs, rhs);
}
}
}
namespace Goo
{
using Baz = Bar<3>;
//#include "foo_operators.h"
namespace Foo
{
int operator+(A const& rhs, A const& lhs)
{
return Baz::plus(lhs, rhs);
}
}
}
using namespace std;
int main()
{
{
using Boo::Foo::operator+;
A a1, a2;
cout << a1 + a2 << endl;
}
{
using Goo::Foo::operator+;
A a1, a2;
cout << a1 + a2 << endl;
}
return EXIT_SUCCESS;
}
// In real code extract to foo_operators.h: the partial file snippets to get #included multiple times
// namespace Foo
// {
// int operator+(A const& rhs, A const& lhs)
// {
// return Baz::plus(lhs, rhs);
// }
// }
The idea is to replace the Foo namespace with a struct template with static methods Bar.
This allows instantiating the Foo type using the desired params.
The operators just call the static methods via the externally defined and parametrized type.
ADL takes care of the rest.
In the example above, the user created 2 new namespaces, Boo and Goo to have 2 different parametrizations of the plus operator. Finally, at the point of usage the user brings in the desired version of the operator+ with the using directive.
In this approach there doesn't seem to be an option for specifying default parameter values.
In real code the operators themselves would be stored in a snippet file to be #includeed into the code after the declaration of the parameterized type (Baz in the example).
Take 2
Here's a much cleaner version that uses a simple templated traits class and avoid both the extra namespace and the operator redirection function plus.
template <int k>
struct op_traits_t
{
static const int K = k;
};
namespace Boo
{
using op_traits = op_traits_t<42>; // same as `typedef op_traits_t<42> op_traits;`
//#include "foo_operators.h"
// this is a partial file snippet
int operator+(A const& rhs, A const& lhs)
{
return rhs.v + lhs.v + op_traits::K;
}
}
namespace Goo
{
using op_traits = op_traits_t<3>;
//#include "foo_operators.h"
// this is a partial file snippet
int operator+(A const& rhs, A const& lhs)
{
return rhs.v + lhs.v + op_traits::K;
}
}
int main()
{
{
using Boo::operator+;
A a1, a2;
cout << a1 + a2 << endl;
}
{
using namespace Goo;
A a1, a2;
cout << a1 + a2 << endl;
}
return EXIT_SUCCESS;
}
std::cout << operator+<12>(a1, a2) << std::endl;
But don't do this. Operator + should behave in an unsurprising way.
Use a named function:
namespace Foo
{
template <int k=11>
int add_plus_k(A const& lhs, A const& rhs)
{
return lhs.v + rhs.v + k;
}
}

operator << overloading in a constructor

I'm debugging a program and I would like to make printing from that pattern:
std::cout << firstVar << ", " << secondVar << ", " << thirdVar << endl ;
shorter, i.e, the same thing should happen if we will write the code:
shortPrint(std::cout) << firstVar << secondVar << thirdVar;
note: there is no limit for the variables quantity, it can be 1 and it can be 20, so that should also work:
shortPrint(std::cout) << firstVar << secondVar << thirdVar << anotherVar << oneMoreVar;
Someone told me that the easiest wat to do that is to create class that is called "shortPrint".
Can anyone help me figuring this out?
For start, I would say that I only need to implement a constructor and operator << overloading, but I'm not sure how to do that exactly in that case.
Yes create a shortPrint class with an appropriate overloaded operator. Something like this :
class shortPrint {
ostream &o;
public:
shortPrint(ostream &o) : o(o) {}
template <typename T> shortPrint &operator<<(const T &t) {
o << t << ',';
return *this;
}
// support for endl, which is not a value but a function (stream->stream)
shortPrint &operator<<(ostream& (*pf)(std::ostream&)) {
o << pf;
return *this;
}
};
That should work (basically).
To eliminate the problem of extra commas use this :
class shortPrint {
class shortPrint2{
shortPrint &s;
public:
shortPrint2(shortPrint &s) : s(s) {}
template <typename T> shortPrint2 &operator<<(const T &t) {
s.o << ',' << t ;
return *this;
}
shortPrint &operator<<(ostream& (*pf)(std::ostream&)) {
s.o << pf;
return s;
}
};
ostream &o;
shortPrint2 s2;
public:
shortPrint(ostream &o) : o(o), s2(*this) {}
template <typename T> shortPrint2 &operator<<(const T &t) {
o << t;
return s2;
}
shortPrint &operator<<(ostream& (*pf)(std::ostream&)) {
o << pf;
return *this;
}
};
You can do something like the following:
class _ostream_wrap
{
public:
template <class T>
_ostream_wrap& operator << (const T & v)
{
m_ost << "[ " << v << " ]";
return (*this);
}
explicit _ostream_wrap(std::ostream & ost)
:m_ost(ost)
{}
private:
std::ostream& m_ost;
};
template <class OSTREAM>
_ostream_wrap shortPrint(OSTREAM & o)
{
return _ostream_wrap(o);
}
//...
shortPrint(std::cout) << 1 << 2;
however this implementation will not work on rvalues:
//you can't do something like the following:
shortPrint(MyOstream(some_args)) << 1;
This is because the class _ostream_wrap keeps a reference to the stream and for rvalues case it needs to make a copy. To make a copy you need to have two implementations (this would be the final version):
template <class OSTREAM>
class _ostream_wrap
{
public:
template <class T>
_ostream_wrap<OSTREAM>& operator << (const T & v)
{
m_ost << "[ " << v << " ]";
return (*this);
}
public:
//the constructor is harder to write so i decided
//that for this i will keep the member public
OSTREAM m_ost;
};
template <class OSTREAM>
_ostream_wrap<OSTREAM&> shortPrint(OSTREAM & o)
{
_ostream_wrap<OSTREAM&> rvalue;
rvalue.m_ost = o;
return rvalue;
}
template <class OSTREAM>
_ostream_wrap<OSTREAM> shortPrint(const OSTREAM & o)
{
_ostream_wrap<OSTREAM> rvalue;
rvalue.m_ost = o;
return rvalue;
}
Here's something with very basic functionality:
#include <iostream>
struct shortPrint {
explicit shortPrint(std::ostream& os)
: strm(&os), first(true) {}
template<typename T>
shortPrint& operator<<(T&& t)
{
if (first) {
first = false;
} else {
*strm << ", ";
}
*strm << std::forward<T>(t);
return *this;
}
shortPrint& operator<<( std::ostream& (*func)(std::ostream&) )
{
*strm << func;
return *this;
}
private:
std::ostream* strm;
bool first;
};
int main()
{
int i = 3;
shortPrint(std::cout) << "1" << 2 << i << std::endl;
shortPrint(std::cout) << 4;
}
The tricky part is getting the commas to be printed correctly. I chose to print them before every streamed object, except before the very first one. As you can see, there's one general operator<< template that simply prints the comma and forwards the argument. The next problem are stream manipulators, because we don't want to print commas before them. The other operator<< overload takes care of that. If you want to be more generic, there's two more you need to take care of (see no. 9 here ).
Hope that helps.
Return the ostream from the function. Something like:
std::ostream &shortPrint(std::ostream &out) {
//whatever you need here
return out;
}
Edit: you the kind of formatting you need, you need to make a class with overloaded stream operator that returns the class. But you need to keep the reference to the needed stream in the class.