Template class and << operator overloading [duplicate] - c++

I'm trying to write a template class which overloads operator==. I know how to get it inside the class:
template <typename T>
class Point
{
private:
T x;
public:
Point(T X) : x(X) {}
bool operator== (Point &cP)
{
return (cP.x == x);
}
};
But now I want to achieve this outside the template class. I've read this post:
error when trying to overload << operator and using friend function and add template declaration in my code:
template <typename> class Point;
template <typename T> bool operator== (Point<T>, Point<T>);
template <class T>
class Point
{
private:
T x;
public:
Point(T X) : x(X) {}
friend bool operator== (Point cP1, Point cP2);
};
template <class T>
bool operator== (Point<T> cP1, Point<T> cP2)
{
return (cP1.x == cP2.x)
}
However I still get a error: unresolved external symbol "bool __cdecl operator==(class Point<int>,class Point<int>)" (??8#YA_NV?$Point#H##0#Z) referenced in function _main
And when I take away friend from :
friend bool operator== (Point cP1, Point cP2);
and want it to be member function, there would be a another error:
too many parameters for this function
why?

#Kühl's answer is the most permissive approach to declare a templated friend function of a templated class. However, there is one unapparent side effect of this approach: All template instantiations of Point are friends with all template instantiations of operator==(). An alternative is to make only the instantiation with the same type of Point a friend. Which is done by adding a <T> in the friend declaration of operator==().
template <typename T> class Point;
template <typename S>
bool operator== (Point<S>, Point<S>);
template <typename T>
class Point {
// ...
friend bool operator==<T> (Point, Point);
};
References
http://web.mst.edu/~nmjxv3/articles/templates.html

The declaration of the operator==() is a template. The declaration made a friend is not a template but a non-template. To make the template operator==() a friend you need to make the friend declaration a template, too:
template <typename T> class Point;
template <typename S>
bool operator== (Point<S>, Point<S>);
template <typename T>
class Point {
// ...
template <typename S>
friend bool operator== (Point<S>, Point<S>);
};

This is a tricky issue: the friend declaration in the class will define a different friend function for each instantiation of your class. In other words, Point<int> and Point<double> will give rise to 2 different non-template friend functions. On the other hand, the outside function is a template function, not related to the friend inside the class. Solution: define the friend function inside the class. Due to friend name injection, it will be found successfully by ADL.

You have to put friend classes within each other, as well as in themselves. The Real one is named syntactically the same without replacing expressions. So friend bool operator==(P<T>,P<T>); goes in both of the classes. So put friend before bool in the class T :-)

Related

Template class with implicit conversion and operator overload but not inline

Based on the answer in Implicit conversion when overloading operators for template classes I was able to write the following code that works perfectly fine (simplified example):
namespace my_library {
template <typename T>
struct Number {
T n;
inline Number(T n) : n(n) { }
friend Number<T> operator+(const Number<T> &a, const Number<T> &b) {
return Number<T>(a.n + b.n);
}
};
}
int main() {
return (int) (4 + my_library::Number<double>(3)).n; // returns 7
}
All I want to do is make it so that operator+ is not inlined within the definition of Number (but stays in the header file) while everything still works the same way - see the expression in the main function. Note that it requires that the integer 4 gets implicitly converted to double and then to Number<double>. I followed a comment linking to Binary operator overloading on a templated class but that solution did not work - the overloaded operator is no longer matched. Is there any way to make this work and have the body of the operator outside the struct definition? (Without complicating the operator interface or adding more overloads - in those cases I'd rather just keep it inlined.)
You can do it like this:
template <typename T>
struct Number {
// ...
template <class U>
friend Number<U> operator+(const Number<U> &a, const Number<U> &b);
};
template <typename U>
Number<U> operator+(const Number<U> &a, const Number<U> &b) {
return Number<U>(a.n + b.n);
}
In this example, operator+ will be a friend of all Number specializations even when the types don't match. This might be a broader friendship than you intended, but is the simplest way to achieve your objective of moving the definition of operator+ outside the definition of Number. Note that when a friend is not defined inline, you lose the benefit of having it as a "hidden friend". (A hidden friend can only be found via argument-dependent lookup, which means that the compiler will typically not have to consider it as a candidate function in most cases where it is not intended to be used.)
If you want each specialization of operator+ to only be a friend of one particular Number specialization where the types match, it is more complicated. You have to forward-declare the operator+ template in order to prevent the friend declaration from declaring a non-template function, and you also have to forward-declare Number so that it can be used in the operator+ forward declaration:
template <typename T> struct Number;
template <typename T>
Number<T> operator+(const Number<T>&, const Number<T>&);
template <typename T>
struct Number {
// ...
friend Number<T> operator+<>(const Number<T>&, const Number<T>&);
};
template <typename T>
Number<T> operator+(const Number<T> &a, const Number<T> &b) {
return Number<T>(a.n + b.n);
}

Why LNK1120 & LNK2019 appears in case of template and friend function

I have compiled the first version of code in Turbo-C and it compiles without any error. But when I compile this in Visual Studio or plain g++ from CommandLine, I get errors mentioned down in the post.
I did searched over internet and read some of the StackOverflow questions & MSDN LNK1120 problem docs. I found a way to fix the below code. However, didn't got the reason clearly. How can just a definition gets rid of that error. Syntactically the error prone code also look fine.
1) Error 2 error LNK1120: 1 unresolved externals
2) Error 1 error LNK2019: unresolved external symbol "void __cdecl
totalIncome(class Husband<int> &,class Wife<int> &)" (?totalIncome##YAXAAV?
$Husband#H##AAV?$Wife#H###Z) referenced in function _main
Note: Please watch out for arrows in program. I've explicitly put them. So, might not go through the complete program.
Error Prone Code:
#include <iostream>
using namespace std;
template<typename T> class Wife; // Forward declaration of template
template<typename T>
class Husband{
friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj);
public:
Husband() = default;
Husband(T new_salary): salary{new_salary} {}
private:
T salary;
};
template<typename T>
class Wife{
friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj);
public:
Wife() = default;
Wife(T new_salary): salary{new_salary} {}
private:
T salary;
};
template<typename T> void totalIncome(Husband<T> &hobj, Wife<T> &wobj) __
{ |
cout << "Total Income of Husband & Wife: "; |
cout << hobj.salary + wobj.salary; |
} |
---
int main()
{
Husband<int> h(40000);
Wife<int> w(90000);
totalIncome(h, w);
return 0;
}
but in the below case by just moving the definition up in the class, it runs perfectly fine. Why whats the reason?
Fixed Code:
#include <iostream>
using namespace std;
template<typename T> class Wife; // Forward declaration of template
template<typename T>
class Husband{
friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj);
public:
Husband() = default;
Husband(T new_salary): salary{new_salary} {}
private:
T salary;
};
template<typename T>
class Wife{
friend void totalIncome(Husband<T> &hobj, Wife<T> &wobj) __
{ |
cout << "Total Income of Husband & Wife: "; | -- definition moved up here
cout << hobj.salary + wobj.salary; |
} __|
public:
Wife() = default;
Wife(T new_salary): salary{new_salary} {}
private:
T salary;
};
/*
template<typename T> void totalIncome(Husband<T> &hobj, Wife<T> &wobj) __
{ |
cout << "Total Income of Husband & Wife: "; |
cout << hobj.salary + wobj.salary; |
} |
---
*/
int main()
{
Husband<int> h(40000);
Wife<int> w(90000);
totalIncome(h, w);
return 0;
}
First, let's cut this down to a minimal example that reproduces the issue:
template<typename T>
class Husband{
friend void totalIncome(Husband<T> &);
};
template<typename T> void totalIncome(Husband<T> &hobj)
{}
int main()
{
Husband<int> h;
totalIncome(h);
}
This leads to a similar linker error. For example, using clang++:
/tmp/main-fb41c4.o: In function `main':
main.cpp:(.text+0xd): undefined reference to `totalIncome(Husband&)'
The underlying issue is the same as the one in Overloaded arithmetic operators on a template causing an unresolved external error and in Strange behavior of templated operator<<. Hence, I'll base my answer here on my answer from the second question.
Friend function declarations
In the class template Husband, there is a friend-declaration of the function totalIncome:
friend void totalIncome(Husband<T> &);
A friend function declaration looks up the name of the declared function (here: totalIncome) in the surrounding scopes up to and including the innermost enclosing namespace. If a declaration of that name is found, the declared entity is befriended:
class Husband;
void totalIncome(Husband&); // (A)
class Husband{
friend void totalIncome(Husband&); // befriends (A)
};
If no declaration of the name is found, a new function is declared in the innermost enclosing namespace:
class Husband{
friend void totalIncome(Husband&); // declares and befriends ::totalIncome
};
void totalIncome(Husband&); // friend of class Husband
If the function is only declared via the friend function declaration (and there is no later declaration in the enclosing namespace), the function can only be found via Argument-Dependent Lookup.
Befriending a function in a class template
The issue in the OP's code is that there is a class template involved:
template<typename T>
class Husband{
friend void totalIncome(Husband<T> &);
};
The rules stay the same: No declaration of totalIncome is found. Since the signature of the friend declaration depends on the template parameter of the class template, every instantiation of Husband will introduce a new function in the enclosing namespace. (If the friend declaration did not depend on a template parameter, you'd get a redeclaration with every instantiation of Husband.) For example, if you instantiate Husband<int> and Husband<double>, you'll get two functions in the global namespace:
void totalIncome(Husband<int> &);
void totalIncome(Husband<double> &);
Note that these are two unrelated functions, much like:
void totalIncome(int &);
void totalIncome(double &);
Overloading a function with a function template
You can overload an "ordinary" function with a function template:
void totalIncome(Husband<int> &); // (A)
template<typename T>
void totalIncome(Husband<T> &); // (B)
When calling the function via Husband<int> x; totalIncome(x);, the function template will produce an instantiation:
void totalIncome<int>(Husband<int> &); // (C), instantiated from (B)
And your overload set consists of two functions:
void totalIncome(Husband<int> &); // (A)
void totalIncome<int>(Husband<int> &); // (C)
All things equal, overload resolution will prefer the non-template function (A) over the function template specialization (C).
And this is what happens in the OP's code as well: There is a non-template function introduced by instantiating the class template Husband, and an unrelated function template. Overload resolution chooses the non-template function, and the linker complains that it doesn't have a definition.
Various solutions
The simplest solution is to define the friend function inside the class definition:
template<typename T>
class Husband{
friend void totalIncome(Husband<T> &){
// code here
}
};
A solution using forward-declarations:
template<typename T>
class Husband;
template<typename T>
void totalIncome(Husband<T> &);
template<typename T>
class Husband{
friend void totalIncome(Husband<T> &);
};
template<typename T> void totalIncome(Husband<T> &hobj)
{}
Here, the compiler can find the forward-declared function template and befriend a specialization of it, instead of declaring a new function. It might be worthwhile explicitly adding the template arguments:
template<typename T>
class Husband{
friend void totalIncome<T>(Husband<T> &);
};
Since this enforces that there is a prior declaration of the function template totalIncome.
A solution befriending the whole function template:
template<typename T>
class Husband{
template<typename U>
friend void totalIncome(Husband<U> &);
};
template<typename T> void totalIncome(Husband<T> &hobj)
{}
In this solution, the friend-declaration declares a function template, and the later declaration at namespace scope following the class' definition redeclares and defines this function template. All specializations of the function template will be befriended by all instantiations of Husband.

C++ class nested into template class

So I have some problems with my template class.
<!-- language: lang-c++ -->
template<class T>
class List {
class Counter
{
T real;
T imaginary;
Counter *next;
//....
public:
Counter(T a=0,T b=0);
virtual ~Counter();
friend ostream& operator<<(ostream&,Counter&);
friend ostream& operator<<(ostream&,List&);
};
Counter* first;
Counter* last;
//....
};
But I have some problems with methods. If i write function as
template<class T> Counter operator/(Counter &one,...)
When I look at Counter in VC++10 it says something like
<error_type>&one
for example. Should I use template<class T> for my Counter class everywhere in the code?
//Methods
//Counter. For example some methods
Counter operator/(Counter& one,Counter& two){}
ostream& operator<<(ostream&os,Counter&x){}
istream& operator>>(istream&is,Counter&x){}
//List
template<class T>void List<T>::add(Counter *T,int i,bool c){}
It depends on whether you define the operators (regardless of whether they are member functions or global operators) inside the class definition or outside of it.
If you do it inside the class definition, there is no need for template<T>, nor for List<T>:
template <typename T>
class List
{
public:
class Counter
{
/* This is a global operator* defined inside the class, and
as friend. */
friend Counter operator*(const Counter &c1, const Counter &c2)
{
return Counter();
}
};
};
(Note that my definition of operator* isn't actually useful because it always returns an empty Counter object. This is just to demonstrate the syntax.)
But if you define the operator outside the class (and therefore outside the template definition for List as well), you have to use the full syntax of a function template definition:
template <typename T>
typename List<T>::Counter operator/(const typename List<T>::Counter &c1, const typename List<T>::Counter &c2)
{
return List<T>::Counter();
}
As you can see, this involves three steps:
Put template <....>, with the names of all template parameters enclosed in <...> before the definition.
Use List<T>::Counter to indicate that Counter is a nested typename
Use typename List<T>::Counter because Counter is nested into a dependent type (i.e. a type that depends on a template argument).

Friend functions of a class template

I have a class template Foo<T>.
I'd like to implement a non-member function Bar that takes two Foos and returns a Foo. I want Bar to be a non-member because it will be more natural for callers to write Bar(f1, f2) than f1.Bar(f2). I also want Bar to be inline because the calculation is trivial and frequent.
template <typename T>
inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) {
...
}
The trick is Bar needs access to Foo's private data. I'd prefer not to have accessors to the private data--there's no good reason to expose the private data to users. So I'd like to make Bar a friend of Foo.
template <typename T>
class Foo {
...
private:
T w, x, y, z;
friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs);
};
Here's where I run into trouble. The compiler complains:
The inline specifier cannot be used when a friend declaration refers to a specialization of a function template.
Is this rule imposed by the standard or is it specific to MSVC++?
Here's what I've tried:
Make Bar a const public member function, and then to declare a non-member version that simply returns lhs.Bar(rhs). This seems the least hacky solution.
Remove the inline hint, knowing that the compiler is going to decide about inlining regardless of the hint. Does this then run afoul of the one-definition rule? It will still have to be defined in a header file because it's a function template.
Declare the member function with a dummy template type:
template <typename T>
class Foo {
...
private:
T w, x, y, z;
// Note that this declaration doesn't actually use Dummy. It's just there to
// satisfy the compiler.
template <typename Dummy>
friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs);
};
I'm not entirely sure why that works, but it does satisfy the compiler.
Is there a better solution?
If the calculation is trivial, I would write:
template <typename T>
class Foo {
...
private:
T w, x, y, z;
public:
friend Foo Bar(const Foo &lhs, const Foo &rhs) {
...
}
};
This doesn't fall foul of the ODR - it's an inline function with external linkage (3.2/5 excludes this from the ODR subject to the definitions being identical, 7.1.2/3 says that it's inline).
However, this doesn't define a function template Bar<T>, it just defines a set of function overloads for Bar. There may be some reason, unstated in the question, that means this won't work for you because you actually need the template.
I like option 1 the best:
template <typename T>
inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) {
return lhs.Bar(rhs);
}
template <typename T>
class Foo {
...
Foo<T> Bar(const Foo<T> &other) const;
private:
T w, x, y, z;
};
Then the functionality is safely contained within the class, but you provide a wrapper function for convenience.
Bar is a template, so it has to be a template in the friend declaration as well.
You don't necessarily have to use a dummy parameter, but could rather use
template <typename U>
friend Foo<U> Bar(const Foo<U> &lhs, const Foo<U> &rhs);
You cannot use T as the template parameter here, as there is already an outer T in scope.

template warnings and error help, (gcc)

I'm working on an container class template (for int,bool,strings etc), and I've been stuck with this error
cont.h:56: error: expected initializer before '&' token
for this section
template <typename T>
const Container & Container<T>::operator=(const Container<T> & rightCont){
what exactly have I done wrong there?.
Also not sure what this warning message means.
cont.h:13: warning: friend declaration `bool operator==(const Container<T>&, const Container<T>&)' declares a non-template function
cont.h:13: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
at this position
template <typename T>
class Container{
friend bool operator==(const Container<T> &rhs,const Container<T> &lhs);
public:
In the first case, you're saying just Container the first time instead of Container<T>.
In the second case, I think you need to repeat the template: while member functions of a template class are implicitly templated, friend functions aren't necessarily, so it's necessary to be more explicitly . I'm not sure what exact syntax you need for that purpose, but I think it is:
before the class, template<typename T> bool operator==( etc
in the class, bool operator==<>( etc
I think that's what the error message is trying to convey, though not super-clearly.
In the first case you've done things backwards. When you specify the return type, you have to include the template parameter list into the template identifier (Container<T>), but when you specify parameter type, you don't need to do it (just Container is enough)
template <typename T>
const Container<T> & Container<T>::operator=(const Container & rightCont){
...
You did it the other way around for some reason.
In the second case, when you declare operator == as a friend it simply warns you that that in this case operator == you are referring to is an ordinary function. It can't be a specialization of a template. I.e. for the class Container<int> the function
bool operator==(const Container<int> &rhs, const Container<int> &lhs) {
// ...
}
will be a friend. But specialization of function template
template <class U>
bool operator==(const Container<U> &rhs, const Container<U> &lhs) {
// ...
}
for U == int will not be a friend of Container<int>. If that's your intent, you are OK.
If you wanted to befriend a specific specialization of the above template, you'd have to say
template <typename T>
class Container {
friend bool operator==<T>(const Container<T> &rhs, const Container<T> &lhs);
...
If you wanted to befriend all specialization of the above template, you'd have to say
template <typename T>
class Container {
template <class U>
friend bool operator==(const Container<U> &rhs, const Container<U> &lhs);
...