Why does this code give me a linker error and how do I fix it?
Undefined symbols for architecture x86_64: "operator==(foo const&, foo const&)", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64
template<typename T>
class foo {
//friends get access to the private member t
friend bool operator==(const foo<T> &lhs, const foo<T> &rhs);
T t;
};
template<typename T>
bool operator==(const foo<T> &lhs, const foo<T> &rhs) {
return lhs.t == rhs.t;
}
int main(int,char**) {
foo<int> f1, f2;
if (f1 == f2)
;
return 0;
}
Here is a fix of your code:
template<typename T>
class foo; // Forward declaration
template<typename T> // Need to define or declare this before the class
bool operator==(const foo<T> &lhs, const foo<T> &rhs) {
return lhs.t == rhs.t;
}
template<typename T>
class foo {
// Notice the little <> here denoting a specialization
friend bool operator==<>(const foo<T> &lhs, const foo<T> &rhs);
T t;
};
operator== is a function template, but the friendship declaration doesn't reflect this. This is one way to fix it:
template <class U>
friend bool operator==(const foo<U> &lhs, const foo<U> &rhs);
One very minor glitch is that it gives operator==<int> friend-access to foo<string>. For this reason, I think #JesseGood's fix is cleaner, albeit (paradoxically) more verbose.
You need to specify the template types again, but different to the class template type:
template<typename V>
friend bool operator==(const foo<V> &lhs, const foo<V> &rhs);
When overloading operators, avoid using friend functions; you'll want to define your function as a public class member, and make it take only one argument (not two).
template<typename T>
class foo {
//public function allowing access to the private member t
public:
bool operator==( foo<T> &rhs)
{
return t == rhs.t;
}
private:
T t;
};
int main(int,char**) {
foo<int> f1, f2;
if (f1 == f2)
;
return 0;
}
Related
I am trying to implement an overload for operator!= that compares two objects of different types (InnerA and InnerB). Both of the types are defined as nested classes within a template class (Outer). The overload needs to be a friend of both classes as it accesses private fields from each.
template<typename Type> class Outer
{
public:
class InnerA;
class InnerB;
};
template<typename Type> bool operator!=(const typename Outer<Type>::InnerA& lhs, const typename Outer<Type>::InnerB& rhs);
template<typename Type> class Outer<Type>::InnerA
{
const int val = 0;
friend bool operator!=<>(const InnerA& lhs, const typename Outer<Type>::InnerB& rhs);
};
template<typename Type> class Outer<Type>::InnerB
{
const int val = 1;
friend bool operator!=<>(const typename Outer<Type>::InnerA& lhs, const InnerB& rhs);
};
template<typename Type> bool operator!=(const typename Outer<Type>::InnerA& lhs, const typename Outer<Type>::InnerB& rhs)
{
return lhs.val != rhs.val;
}
int main()
{
bool b = Outer<int>::InnerA() != Outer<int>::InnerB();
}
The above code fails to compile, emitting:
In instantiation of 'class Outer<int>::InnerA':
34:33: required from here
15:17: error: template-id 'operator!=<>' for 'bool operator!=(const Outer<int>::InnerA&, const Outer<int>::InnerB&)' does not match any template declaration
In instantiation of 'class Outer<int>::InnerB':
34:57: required from here
22:17: error: template-id 'operator!=<>' for 'bool operator!=(const Outer<int>::InnerA&, const Outer<int>::InnerB&)' does not match any template declaration
In function 'int main()':
34:35: error: no match for 'operator!=' (operand types are 'Outer<int>::InnerA' and 'Outer<int>::InnerB')
34:35: note: candidate is:
26:30: note: template<class Type> bool operator!=(const typename Outer<Type>::InnerA&, const typename Outer<Type>::InnerB&)
26:30: note: template argument deduction/substitution failed:
34:57: note: couldn't deduce template parameter 'Type'
While there might be better ways to achieve a similar result, I'm curious as to what precisely is wrong with my code. Thanks!
template<typename Type> class Outer<Type>::InnerA
{
friend bool operator!=(const InnerA& lhs, const typename Outer<Type>::InnerB& rhs) { return true; }
};
template<typename Type> class Outer<Type>::InnerB
{
friend bool operator!=(const typename Outer<Type>::InnerA& lhs, const InnerB& rhs) { return true; }
};
these are non-template friends. They also conflict. So implement one of them, omit the other.
They will be found via ADL.
I found the following workaround, refactoring the overload as a method of one of the nested classes:
template<typename Type> class Outer
{
public:
class InnerA;
class InnerB;
};
template<typename Type> class Outer<Type>::InnerA
{
const int val = 0;
public:
bool operator!=(const typename Outer<Type>::InnerB& other);
};
template<typename Type> class Outer<Type>::InnerB
{
const int val = 1;
friend bool Outer<Type>::InnerA::operator!=(const InnerB& other);
};
template<typename Type> bool Outer<Type>::InnerA::operator!=(const typename Outer<Type>::InnerB& other)
{
return val != other.val;
}
int main()
{
bool b = Outer<void>::InnerA() != Outer<void>::InnerB();
}
However, I am still curious if the same can be accomplished using a non-member friend function as in the question.
The issue with the code in the question ended up being that template deduction is not attempted on type names nested inside a dependent type (e.g. Outer<Type>::Inner).
This question is essentially a duplicate of Nested template and parameter deducing. A detailed explanation on why this is a problem can be found here.
I want to add some friend declarations to a class. For example, I want to add some functions of operator== ,operator <. So what I have to do is use the forward declarations:
template <typename >
class MyBlob;
template <typename T>
bool operator==(const MyBlob<T> &, const MyBlob<T>&);
template <typename T>
bool operator!=(const MyBlob<T> &, const MyBlob<T>&);
template <typename T>
bool operator<(const MyBlob<T> &, const MyBlob<T>&);
template <typename T>
class MyBlob
{
friend bool operator== <T>(const MyBlob<T> &lhs,const MyBlob<T> &rhs);
friend bool operator!= <T>(const MyBlob<T> &lhs,const MyBlob<T> &rhs);
friend bool operator< <T>(const MyBlob<T> &lhs,const MyBlob<T> &rhs);
//other things
};
This is annoying that I have to use template <typename T> for three times. And this really reduce the readability.
So, is there any method to make the forward declaration more simple? Or can I have some method to declare these things in one place just like the ordinary function?
If this can't be done, Is using typedef to simplify the template <typename T> a good idea?
You can try defining friend operators within the class declaration:
template <typename T>
class MyBlob {
friend bool operator== (const MyBlob& lhs, const MyBlob& rhs) {
// ...
}
friend bool operator!= (const MyBlob& lhs, const MyBlob& rhs) {
// ...
}
friend bool operator< (const MyBlob& lhs, const MyBlob& rhs) {
// ...
}
// ...
};
I have a class template and an operator template that needs to access its private field. I can make a template friend:
template <typename T>
class A {
int x;
template <typename U>
friend bool operator==(const A<U>& a, const A<U>& b);
};
template <typename T>
bool operator== (const A<T>& a, const A<T>& b) {
return a.x == b.x;
}
int main() {
A<int> x, y;
x == y;
return 0;
}
But is it possible to make only operator==<T> friend for A<T> and not making operator==<int> friend of A<double> ?
If having trouble with friend, then bring the declaration forward, before the A class is defined.
template <typename T>
bool operator== (const A<T>& a, const A<T>& b);
Then you can friend it more clearly. Full solution (ideone):
template <typename T>
class A;
// declare operator== early (requires that A be introduced above)
template <typename T>
bool operator== (const A<T>& a, const A<T>& b);
// define A
template <typename T>
class A {
int x;
// friend the <T> instantiation
friend bool operator==<T>(const A<T>& a, const A<T>& b);
};
// define operator==
template <typename T>
bool operator== (const A<T>& a, const A<T>& b) {
return a.x == b.x;
}
Yes you can. The syntax is as follows:
template <typename T>
class A {
int x;
friend bool operator==<>(const A& a, const A& b);
};
And put your operator== definition(or just a declaration) before the A class.
I create a template class and want to overload an operator + (several times). I do this in the following way
template <typename T> class Polynomial;
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);
....
template <typename T>
class Polynomial {
....
public:
....
Polynomial operator +(const Polynomial& other) const {
// impelementation
}
friend const Polynomial<T> operator + <> (const Polynomial<T>& poly, const T& scalar);
};
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
// implementation
}
However, I got the following error (which corresponds to the line that begins with 'friend')
problem2.cpp:282:45: error: declaration of ‘operator+’ as non-function
problem2.cpp:282:45: error: expected ‘;’ at end of member declaration
problem2.cpp:282:47: error: expected unqualified-id before ‘<’ token
Following Raxvan's advise, I've changed the code
template class Polynomial;
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);
template <typename T>
ostream& operator <<(ostream& out, const Polynomial<T>& other);
....
template <typename T>
class Polynomial {
....
public:
....
friend ostream& operator << <> (ostream& out, const Polynomial<T>& other);
Polynomial operator +(const Polynomial& other) const {
// impelementation
}
template <typename NOT_T>
friend const Polynomial<NOT_T> operator +(const Polynomial<NOT_T>& poly, const NOT_T& scalar);
};
template <typename T>
ostream& operator <<(ostream& out, const Polynomial<T>& other) {
// implementation
}
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
// implementation
}
And in this code I don't have problems with operator << as I had with operator +. Can anyone explain the defference?
The problem is subtle. Your syntax is very close to being
correct. I think your friend declaration should be:
friend Polynominal<T> const operator+<T>( ... );
but both VC++ and g++ accept:
friend Polynominal<> const operator+<T>( ... );
when they can see the declaration:
template <typename T>
const Polynomial<T> operator+(const Polynomial<T>& poly, const T& scalar);
(I can't find anything in the standard to justify this off hand,
but since both VC++ and g++ do it, I suppose that it's something
I've missed.)
And therein lies the problems. The declaration at namespace
scope of operator+ is hidden by the in-class definition. The
compiler complains because the operator+ it finds (the in
class definition) isn't a template itself (although it is
a member of a class template).
If you don't have the problem with operator<<, it's because
you don't have a member function with the same name.
There are several ways of solving this problem. The simplest is
probably to make all of the operator+ friends. Or not: the
most common approach to this is to implement operator+ in
terms of operator+= (which should be a member, in all cases).
In which case, operator+ doesn't have to be a friend.
Or you don't make operator+ a template at all, but definite it
inside your class template:
template <typename T>
class Polynomial
{
friend Polynomial operator+( Polynomial const& lhs, Polynomial const& rhs )
{
// ...
}
friend Polynomial operator+( Polynomial const& lhs, T const& rhs )
{
// ...
}
friend Polynomial operator+( T const& lhs, Polynomial const& rhs )
{
// ...
}
}
(Note that the functions being defined are not templates, but
separate overloaded non-template functions, one for each
instantiation of Polynomial. But the results end up being the
same.)
In this case, you probably would want to have a member function,
called by the operator+ functions, which would do the actual
work; you don't want too much code directly inline like this.
Your operator+ is a function template, to make this a friend, you need to declare it fully including the template parameters, however with a different template parameter, for example:
#include <iostream>
template <typename T> class Polynomial;
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);
template <typename T>
class Polynomial {
public:
Polynomial operator +(const Polynomial& other) const {
std::cout << "inline +" << std::endl;
}
// Here introduce a different type to indicate that this is a template...
template <typename U>
friend const Polynomial<U> operator + (const Polynomial<U>& poly, const U& scalar);
};
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
std::cout << "friend +" << std::endl;
}
int main(void)
{
Polynomial<int> f;
f = f + 1;
f = f + 1.; // this fails
f = f + Polynomial<int>();
}
You have to have the same definition when you label a function as friend, this includes the template used above with another type , not T
template <typename T> class Polynomial;
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);
template <typename T>
class Polynomial {
public:
template < class NOT_T> //must respect the deffinition from above
friend const Polynomial<NOT_T> operator + (const Polynomial<NOT_T>& poly, const NOT_T& scalar);
};
template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar)
{
//...
}
Edit:
For a simplified explanation i have changed the function to foo and bar to illustrate the difference in declarations:
template <typename T> class Polynomial;
template <typename T>
void bar(const Polynomial<T>& );
void foo(const Polynomial<float> & );//foo for speciffic float
template <typename T>
class Polynomial {
public:
template <typename> //this is also valid declaration;
friend void bar(const Polynomial<T> & );
//it just has to have template because it's a template functions declaration
//not a valid declaration:
//friend void bar <> (const Polynomial<T> & );
//this declaration has no template;
//it refers to a foo function specific to Polynomial<T> type
//so if you use Polynomial<float> there must be a foo for floats
friend void foo(const Polynomial<T> &);
};
template <class T>
void bar(const Polynomial<T>&)
{
}
void foo(const Polynomial<float> &)
{
}
void main()
{
Polynomial<float> pf;
Polynomial<int> pi;
foo(pi);//error since there is not **foo** declared for int
foo(pf);//ok; we have **foo** for Polynomial<float>
bar(pf);
bar(pi);//both ok since bar is templated function;
}
Raxvan.
This will not work
template<typename T>
struct foo {
T t;
};
bool operator==(const foo &lhs, const foo &rhs) { //error, requires template arg
return lhs.t == rhs.t;
}
Is this the correct way to solve this? I want define also the operators <,>,<=,>=,!= so doing template<typename T> on all of them would be lengthy.
template<typename T>
struct foo {
T t;
};
template<typename T>
bool operator==(const foo<T> &lhs, const foo<T> &rhs) {
return lhs.t == rhs.t;
}
There are two solutions: you can define them as const member functions inside the class
template<typename T>
struct foo {
T t;
bool operator==(const foo &lhs, const foo &rhs) const { return lhs.t == rhs.t; }
// same for the other relational operators
};
This works because inside the class you can use foo as a shorthand for foo<T>.
An alternative is to define them as friend non-member functions inside the class
template<typename T>
class foo {
T t;
friend bool operator==(const foo &lhs, const foo &rhs) const { return lhs.t == rhs.t; }
// same for the other relational operators
};
If you define t as a private member, then you actually need to make operator== a friend function in order to let it gain access. Note however, that this will have the side-effect as injecting them as non-member non-template functions in the surrounding namespace. This has some consequences for argument-dependent name lookup.
if you don't care about implicit conversions, you can set them as member functions, so you won't have to retype it each time.
but if you have to define them as free functions, I'm afraid you don't have a choice.