By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,421 Members | 1,053 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,421 IT Pros & Developers. It's quick & easy.

linker errors when I use template friends?

P: n/a

Actually, I also got linker errors with template functions and template
classes. And I avoided both of them successfully, by pouring foo.cpp
into foo.h, according to the C++ FAQ.

(http://www.parashift.com/c++-faq-lit...templates.html)

And then, I pre-declared each template friend function above the
definition of template class. But I still get template friends linker
error. My compiler is gcc 3.3.3. Any hints? Thanks,

--
William Xuuu
Jul 22 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a

"william xuuu" <ab*@abc.abc> wrote in message news:87************@abc.abc...

Actually, I also got linker errors with template functions and template
classes. And I avoided both of them successfully, by pouring foo.cpp
into foo.h, according to the C++ FAQ.

(http://www.parashift.com/c++-faq-lit...templates.html)

And then, I pre-declared each template friend function above the
definition of template class. But I still get template friends linker
error. My compiler is gcc 3.3.3. Any hints? Thanks,


Probably your 'pre-declaration' is not the same as your actual definition.
So the linker tries to find the definiton for you pre-declaration and finds
nothing. Show us the code.

Don't #include foo.cpp in foo.h, that just makes things unnecessarily
complicated. Put everthing into foo.h and throw away foo.cpp. You know it
makes sense.

john
Jul 22 '05 #2

P: n/a
"John Harrison" <jo*************@hotmail.com> writes:
Probably your 'pre-declaration' is not the same as your actual definition.
So the linker tries to find the definiton for you pre-declaration and finds
nothing. Show us the code.


Okay, here it is: (only two files)
//----------------------- "vector_set.h"

//pre declarations.
template <typename T> class Vector_Set;
template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
const Vector_Set<T>& s2);

//begin class itself
template <typename T> class Vector_Set
{
friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
public:
...
};

// friends implementation
template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
const Vector_Set<T>& s2)
{
...
}

//----------------------- "vector_set_main.cpp"

typedef Vector_Set<int> Set;

Set a = Set(10), b = Set(10);
for(int i = 0; i < a.size(); i++)
if(i % 2 == 1)
a.add_member(i);
else
b.add_member(i);

// Here causes error!
a + b;

warnings and errors:

g++ -c vector_set_main.cpp
In file included from vector_set_main.cpp:8:
vector_set.h:29: warning: friend declaration `Vector_Set<T> operator+(const
Vector_Set<T>&, const Vector_Set<T>&)' declares a non-template function
g++ -g vector_set_main.o -O2 -lm -o vector_set_main
vector_set_main.o(.text+0x172): In function `main':
: undefined reference to `operator+(Vector_Set<int> const&, Vector_Set<int> const&)'

does this help?

--
William Xuuu
Jul 22 '05 #3

P: n/a
> template <typename T> class Vector_Set
{
friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
This is a non-template function. It declares (as a friend) this function

Vector_Set<int> operator+ (const Vector_Set<int>& s1, const Vector_Set<int>&
s2);

typedef Vector_Set<int> Set;

Set a = Set(10), b = Set(10);
for(int i = 0; i < a.size(); i++)
if(i % 2 == 1)
a.add_member(i);
else
b.add_member(i);

// Here causes error!
a + b;


Now the compiler thinks there are two functions to choose from, the
non-template (which you declared as a friend)

Vector_Set<int> operator+ (const Vector_Set<int>& s1, const Vector_Set<int>&
s2);

and the template (which you pre-declared)

template <class T>
Vector_Set<T> operator+ (const Vector_Set<T>& s1, const Vector_Set<T>& s2);

Given this choice the compiler always prefers the non-template. But since
you didn't define a non-template you get a link error.

The answer is to tell the compiler that the friend declaration refers to a
template function. You do that by adding '<T>' or '<>' after operator+.

template <typename T> class Vector_Set
{
friend Vector_Set<T> operator+ <>(const Vector_Set<T>& s1, const
Vector_Set<T>& s2);

It's easy to forget that you can have template and non-template versions of
the same function.

john
Jul 22 '05 #4

P: n/a
> The answer is to tell the compiler that the friend declaration refers to a
template function. You do that by adding '<T>' or '<>' after operator+.


Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
with <>.

john
Jul 22 '05 #5

P: n/a
In article <87************@abc.abc>, William Xuuu <ab*@abc.abc> wrote:
"John Harrison" <jo*************@hotmail.com> writes:
Probably your 'pre-declaration' is not the same as your actual definition.
So the linker tries to find the definiton for you pre-declaration and finds
nothing. Show us the code.


Okay, here it is: (only two files)
//----------------------- "vector_set.h"

//pre declarations.
template <typename T> class Vector_Set;
template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
const Vector_Set<T>& s2);

//begin class itself
template <typename T> class Vector_Set
{
friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
public:
...
};

// friends implementation
template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
const Vector_Set<T>& s2)
{
...
}

//----------------------- "vector_set_main.cpp"

typedef Vector_Set<int> Set;

Set a = Set(10), b = Set(10);
for(int i = 0; i < a.size(); i++)
if(i % 2 == 1)
a.add_member(i);
else
b.add_member(i);

// Here causes error!
a + b;

warnings and errors:

g++ -c vector_set_main.cpp
In file included from vector_set_main.cpp:8:
vector_set.h:29: warning: friend declaration `Vector_Set<T> operator+(const
Vector_Set<T>&, const Vector_Set<T>&)' declares a non-template function
g++ -g vector_set_main.o -O2 -lm -o vector_set_main
vector_set_main.o(.text+0x172): In function `main':
: undefined reference to `operator+(Vector_Set<int> const&, Vector_Set<int> const&)'

does this help?


Like John and your warning say: the decl is not the same
as the definition. Your fried declares a non-template op+ however
your definition is for a template one. Figure out which you
need and use the same for both.
--
Greg Comeau / Comeau C++ 4.3.3, for C++03 core language support
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Jul 22 '05 #6

P: n/a
"John Harrison" <jo*************@hotmail.com> writes:
The answer is to tell the compiler that the friend declaration refers to a
template function. You do that by adding '<T>' or '<>' after operator+.

Hmm, it works fine by adding <> or <T> as follows.

//begin class itself
template <typename T> class Vector_Set
{

friend Vector_Set<T> operator+<T> (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
};

While, the C++ FAQ didn't add <> or <T> ?!

Then I find it's not allowed to use + as:

a +<int> b;

So ?
Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
with <>.


Could you explain the differences between <T> and <> ?

And, i find that either adding <T> after pre-declaration or its
implementation, as:

//pre declarations.
template <typename T> class Vector_Set;
template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
const Vector_Set<T>& s2);
// friends implementation
template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
const Vector_Set<T>& s2)
{ ... }
both would cause same error:

error: partial specialization `operator+<T>' of function template

Why would it happen?

--
William Xuuu
Jul 22 '05 #7

P: n/a
In article <87************@abc.abc>, William Xuuu <ab*@abc.abc> wrote:
"John Harrison" <jo*************@hotmail.com> writes:
The answer is to tell the compiler that the friend declaration refers to a
template function. You do that by adding '<T>' or '<>' after operator+.

Hmm, it works fine by adding <> or <T> as follows.

//begin class itself
template <typename T> class Vector_Set
{

friend Vector_Set<T> operator+<T> (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
};

While, the C++ FAQ didn't add <> or <T> ?!

Then I find it's not allowed to use + as:

a +<int> b;

So ?


Not sure what you're asking, but perhaps you're looking for
the long-hand version like a.operator+<int>(b);
Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
with <>.


Could you explain the differences between <T> and <> ?

And, i find that either adding <T> after pre-declaration or its
implementation, as:

//pre declarations.
template <typename T> class Vector_Set;
template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
const Vector_Set<T>& s2);
// friends implementation
template <typename T> Vector_Set<T> operator+<T> (const Vector_Set<T>& s1,
const Vector_Set<T>& s2)
{ ... }
both would cause same error:

error: partial specialization `operator+<T>' of function template

Why would it happen?


Because a "primary" template declaration should not mention
it's arguments on its name, which the <T> would do above, but
since it's declared above, the friend is using it in your case,
not declaring it as such.
--
Greg Comeau / Comeau C++ 4.3.3, for C++03 core language support
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Jul 22 '05 #8

P: n/a
co****@panix.com (Greg Comeau) writes:
Hmm, it works fine by adding <> or <T> as follows.

//begin class itself
template <typename T> class Vector_Set
{

friend Vector_Set<T> operator+<T> (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
};

While, the C++ FAQ didn't add <> or <T> ?!

Then I find it's not allowed to use + as:

a +<int> b;

So ?


Not sure what you're asking, but perhaps you're looking for
the long-hand version like a.operator+<int>(b);


Right, a.operator+<int>(b), when we declare it to be a member of a
class. But here it's declared as a friend function! So don't we have to
specifly <T> as well? i.e, a +<int> b

--
William Xuuu
Jul 22 '05 #9

P: n/a

"William Xuuu" <ab*@abc.abc> wrote in message news:87************@abc.abc...
"John Harrison" <jo*************@hotmail.com> writes:
The answer is to tell the compiler that the friend declaration refers to a template function. You do that by adding '<T>' or '<>' after operator+.


Hmm, it works fine by adding <> or <T> as follows.


The following code produces compiler errors on gcc.

#include <iostream>
using namespace std;

template <typename T> class Vector_Set;
template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
const Vector_Set<T>& s2);

template <typename T> class Vector_Set
{
friend Vector_Set<T> operator+ <T> (const Vector_Set<T>& s1, const
Vector_Set<T>& s2);
};

template <typename T> Vector_Set<T> operator+ (const Vector_Set<T>& s1,
const Vector_Set<T>& s2)
{
return s1;
}

int main()
{
typedef Vector_Set<int> Set;
Set a, b;
a + b;
}

Change <T> to <> in the friend declaration and it compiles, remove using
namespace std and it compiles. I think its a gcc bug.

john
Jul 22 '05 #10

P: n/a
> >>
Then I find it's not allowed to use + as:

a +<int> b;

So ?


Not sure what you're asking, but perhaps you're looking for
the long-hand version like a.operator+<int>(b);


Right, a.operator+<int>(b), when we declare it to be a member of a
class. But here it's declared as a friend function! So don't we have to
specifly <T> as well? i.e, a +<int> b


I think you're confused, a.operator+<int>(b) isn't a declaration, its a
function call.

a + b works because in C++ the template function to call is deduced from the
types of the arguments. You can specify the type by appending them after the
function name

func<int>(a, b)

if you want or need to be explicit about template parameters but this syntax
isn't available for the operator form of a function call, which is why Greg
advised

a.operator+<int>(b)

john
Jul 22 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.