Unable match function definition to an existing definition in templated class - c++

I'm sorry if such a question is asked before but i could not find no matter how much I searched (there were similar questions but none of them seemed to work for me).
I am writing a templated class and everything works fine except when I try to overload operator+. I try to overload operator+ two times for different parameters but compiler does not see one of the definitions and gives an eror. Here's the code:
Worker.h (one of my previos homeworks, implemented the problem here since it is easier to see ):
#ifndef _WORKER_H
#define _WORKER_H
#include <string>
#include "Project.h"
using namespace std;
template <class T>
class Worker {
public:
Worker(const string &, Project &);
void Work(const int &);
const Worker & Worker::operator+(const int &); //Problem
const Worker & Worker::operator+(const string &); //Problem
string getName() const;
int getTime() const;
private:
string myName; //The name of the worker
Project & myProject;
int myTime; //Variable to keep track of how much the worker worked.
};
#include "Worker.cpp"
#endif
and the relevant part of Worker.cpp:
template <class T>
const Worker<T> & Worker<T>::operator+(const int & add)
{
cout << add;
return *this;
}
template <class T>
const Worker<T> & Worker<T>::operator+(const string & add)
{
cout << add;
return *this;
}
+ operators are not doing anything right now, the problem is the compiler only sees first declared function (in this case the with the parameter int). There also does not seem to be problem with the functions because if I try to overload only one time, both of them work fine alone. Also I can use them (making the necessary changes) in a non-templated class.
I think it is something simple but since I'm new to templates I could not figure out what the problem was.

There are a few problems with your approach, unrelated to templates.
First your operators would only work for one ordering of operations: Worker<T> + int, and not int + Worker<T>
Second typically you would want to return a new Worker instance, not return this by reference, because A+Bshould not modify A or B.
So what you could do is define non-member operators for the different orderings:
template <typename T>
Worker<T> operator+(int i, const Worker<T>& t) { }
template <typename T>
Worker<T> operator+(const Worker<T>& t, int i) { }
and so on.
Note that for operators that should affect the state of the object, such as +=, *= and so on, the usual approach is to use member operators and return by reference, because in these cases it makes perfect sense.

2 things here, 1 of which is your issue
The return type of a member function is not affected by the fact that the class is a template, hence the declaration of operator+ returning Worker and the definition returning Worker<T> are different. In the class definition, they should be:
const Worker<T> & operator+(const int &); //Problem
const Worker<T> & operator+(const string &); //Problem
The other thing which is also changed in the above code is you don't need the scope (Worker::) in a class declaration

Related

How can I pass an object as an argument to one of its member functions?

I created a class bigInt in c++. While overloading some of its operators, I need to pass the object itself as an argument to one of its member functions. I know that I can do this with *this. I can also do it by creating another object of the same class with the same member variables and pass it as an argument. But is there any way I can skip *this and also not create another object?
Here is the code I have made using *this:
using namespace std;
class bigInt {
private:
string value;
public:
template<class T>
bigInt(T x) {
//.... .... ....constructor
}
bigInt operator+ (bigInt num) {
//... ... ... my code here
}
template<class T>
bigInt operator+ (T x) {
return *this + bigInt(x);
}
};
And here is the code where I created another object of the class bigInt:
using namespace std;
class bigInt {
private:
string value;
public:
template<class T>
bigInt(T x) {
//.... .... ....constructor
}
bigInt operator+ (bigInt num) {
//... ... ... my code here
}
template<class T>
bigInt operator+ (T x) {
return bigInt(value) + bigInt(x);
}
};
Please tell me how I can do the same thing without using *this or creating another object?
N.B. I heard that using the this pointer is generally considered a bad programming practice. Is it true or not? If it is true, is there any case where it is not considered a bad practice?
Update: It's perfectly okay to use *this in this context. The article that inspired me to ask this question was talking about something else completely. But as a newbie programmer, I didn't understand the context there.
The templated operator+ is superfluous; just remove it.
In other news:
Consider also changing bigInt operator+ (bigInt num) to bigInt operator+ (bigInt const& num) to avoid needless inefficiency.
Also, consider making it a friend function so that order of arguments doesn't matter.

Declaring = and [] operators for a class on the header file, "must be a nonstatic member function" error

I've made a class Block and a struct coords and while implementing the operators i came up with the errors:
'coords operator[](const Block&, const size_t&)' must be a nonstatic member function
'bool operator=(Block&, const Block&)' must be a nonstatic member function
I've declared these 2 in the header file of the class Block as follows:
class Block
{
friend Block operator+(const Block&, const coords&);
friend Block operator+(const Block&, const Block&);
friend coords operator[](const Block&, const std::size_t&);
friend void operator+=(Block&, const coords&);
friend void operator+=(Block&, const Block&);
friend bool operator=(Block&, const Block&);
//...
};
Only the operators [] and = get this error, and I'm not sure why.
I've tried to change the return value and parameter types but it keeps getting the same problem.
Are these two operators special? Or is there an error on my declarations?
I've searched for ways to solve this problem, but couldn't find a suitable answer.
Thank you for the replies.
Not all operators can be overloaded using non-member functions. [] and = are two such operators. They can be overloaded only as member functions.
See http://en.cppreference.com/w/cpp/language/operators for more details.
Those operators cannot be declared as friends. Instead you should declare like this:
coords operator[](const std::size_t&);
bool operator=(const Block&);
Your operators are also not really following conventions. Operators += and = should be returning a Block& namely *this.
The reason is exactly what the error message says: those two have to be non-static member functions. Get rid of the friend from in front of them and remove the first argument.
Further, operator+= is usually implemented as a member function, too, although it doesn't have to be. But if it is, it gives you an easy way to implement operator+ without making it a friend.
#R Sahu's link was useful, showing that [] and = can no be declared as non-member, but it didn't really explain why.
#Baum mit aguen's link cleared some other questions too.
(Thanks for the information)
So, I adjusted my code to this new information as follows:
Block.h
class Block
{
public:
//...
coords* operator[](size_t);
Block operator=(Block);
//...
};
Block.cpp
//...
coords* Block::operator[](size_t index)
{
if(index >= 0 && index < block.size())
return &block.at(index);
coords *tmp = new coords(-1, -1);
return tmp;
}
Block Block::operator=(Block b2)
{
block.empty();
block.reserve(b2.block.size());
append(b2.block);
return *this;
}
//...
This way you can call *(*b1)[0] = c1; being Block* b1 and coords c1.
The friend modifier is useful for other types of implementations, although I only realized after that the implementation of inline had to be done in the header file, not on the cpp.
Block.h
class Block
{
public:
//...
friend std::ostream& operator<<(std::ostream&, const Block&);
friend std::ostream& operator<<(std::ostream&, Block&);
//...
};
inline std::ostream& operator<<(std::ostream& out, const Block& b)
{
// do something
return out;
};
inline std::ostream& operator<<(std::ostream& out, Block& b)
{
// do something
return out;
};
In this case, you need to pass the "this" parameter has to be passed to the function also as these are non-member functions and should be implemented outside the class, in the header file.
I hope this helps, good coding everyone.

Overloading operator T***()

I don't know, why my code doesn't work. I create struct and inside put overloading operatoroperator T***(), In main I'd like using following notation const int * const * const * p1 = a;
struct A{
template<class T> operator T***(){}
};
int main(){
A a;
const int * const * const * p1 = a;
return 0;
}
Error: undefined reference to '_ZN1AcvPPPT_IKiEEv'
You simply missed to give your type conversion function an implementation
struct A{
template<class T> operator T***() {
return nullptr; // Do whatever you want to do here.
}
};
See a working sample please.
I have absolutely no idea what you are trying to do, but your problem is a linker problem. You just declare (but not define) the conversion operator T***. You have to define it,
template<class T> operator T***()
{
// define it here
}
Before you edited the question:
template<class T> operator T***();
declares the operator template, but doesn't define it, hence the error that it's undefined. You'll get that error even if you define the template in another source file, since templates must be defined in every translation unit that uses them.
After the edit:
template<class T> operator T***(){}
the code compiles, but has undefined behaviour since the operator is missing a return statement.

correct way to implement operator== in .cpp file [duplicate]

This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 8 years ago.
i have a class which needs to implement the operator== and return type of it is bool. I'm not sure is below code the correct way to implement it.
//MyTest.hpp file
class Test {
public:
Test();
virtual ~Test();
int x,y;
bool operator==(const Test &v);
};
// MyTest.cpp file
bool Test::operator==(const Test &v) {
return (x== v.x) && (y==v.y);
}
even though the code compiles is this standard way to implement we need to use template.
Should i use template way of implementation like below code :
template <class T>
bool operator==(const T &v);
Don't use templates unless you need to. Does it make sense for Test to be comparable with any type? I doubt so.
Also there's no "Standard way" because the standard does not impose a strict way to implement operator== (I think it mentions something on the return type, but I doubt it actually enforces anything).
It's a good idea to make it return a bool and make it does what people expect it does (compare the two objects in a meaningful way).
And finally, you should mark your current one const:
bool operator==(const Test &v) const;
Unless it actually modifies the invoking object, which is definitely something you don't want it to do.
As others have mentioned, using a template without any reason to do so is neither standard nor recommended. However assuming you want operator== to be more like one of the default comparison operators you should either mark it const (otherwise you cannot compare two const Test) like so
class Test {
public:
Test();
virtual ~Test();
int x,y;
bool operator==(const Test &v) const;
};
// MyTest.cpp file
bool Test::operator==(const Test &v) const {
return (x== v.x) && (y==v.y);
}
, or make it a free function (in the same namespace for ADL) taking two const Test & (preferred) like so
class Test {
public:
Test();
virtual ~Test();
int x,y;
};
bool operator==(const Test &a, const Test &b);
// MyTest.cpp file
bool operator==(const Test &a, const Test &b) {
return (a.x==b.x) && (a.y==b.y);
}
If any access to private members is required the free function can always be marked friend. In simple cases such as the one in this example it can be advantageous to furthermore define it in the header and marking it inline.
Please do not use templates matching anything:
template <class T>
bool operator==(const T &, const T &);
That one will put you in all kinds of trouble !

Compilation error about operator reloading using boost::variant

I'am trying to learn boost.variant. However, the code which I copied from a book won't pass the compilation:
class var_print : public boost::static_visitor<void>
{
public:
template<typename T>
void operator()(T &i) {
i *= 2;
cout<<i<<endl;
}
};
Here is how I tried to use it.
typedef boost::variant<int,double,string> var_t;
var_t v(1); //v->int
boost::apply_visitor(var_print(),v);
The compiler generates the following error:
ERROR:no match for 'operator*=' in 'i *= 2'
That puzzles me,since template function will determine the type of parameter whenever it's called and int should defined the operator *=.
You need to have a separate operator() for std::string& since no operator *= is defined for std::string.
In addition, your operator must be marked const since you are passing a temporar visitor instance to apply_visitor.