Connecting Tech Pros Worldwide Forums | Help | Site Map

linker errors when I use template friends?

william xuuu
Guest
 
Posts: n/a
#1: Jul 22 '05

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

John Harrison
Guest
 
Posts: n/a
#2: Jul 22 '05

re: linker errors when I use template friends?



"william xuuu" <abc@abc.abc> wrote in message news:87r7tkiz7f.fsf@abc.abc...[color=blue]
>
> 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,
>[/color]

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


William Xuuu
Guest
 
Posts: n/a
#3: Jul 22 '05

re: linker errors when I use template friends?


"John Harrison" <john_andronicus@hotmail.com> writes:
[color=blue]
> 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.[/color]

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
John Harrison
Guest
 
Posts: n/a
#4: Jul 22 '05

re: linker errors when I use template friends?


> template <typename T> class Vector_Set[color=blue]
> {
> friend Vector_Set<T> operator+ (const Vector_Set<T>& s1, const
> Vector_Set<T>& s2);[/color]

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);
[color=blue]
>
> 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;
>[/color]

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


John Harrison
Guest
 
Posts: n/a
#5: Jul 22 '05

re: linker errors when I use template friends?


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

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

john


Greg Comeau
Guest
 
Posts: n/a
#6: Jul 22 '05

re: linker errors when I use template friends?


In article <87sme0o2jt.fsf@abc.abc>, William Xuuu <abc@abc.abc> wrote:[color=blue]
>"John Harrison" <john_andronicus@hotmail.com> writes:[color=green]
>> 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.[/color]
>
>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?[/color]

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?
William Xuuu
Guest
 
Posts: n/a
#7: Jul 22 '05

re: linker errors when I use template friends?


"John Harrison" <john_andronicus@hotmail.com> writes:
[color=blue][color=green]
>> 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+.
>>[/color][/color]

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 ?
[color=blue]
> Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
> with <>.[/color]

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
Greg Comeau
Guest
 
Posts: n/a
#8: Jul 22 '05

re: linker errors when I use template friends?


In article <87hdug7yx2.fsf@abc.abc>, William Xuuu <abc@abc.abc> wrote:[color=blue]
>"John Harrison" <john_andronicus@hotmail.com> writes:
>[color=green][color=darkred]
>>> 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+.
>>>[/color][/color]
>
>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 ?[/color]

Not sure what you're asking, but perhaps you're looking for
the long-hand version like a.operator+<int>(b);
[color=blue]
>[color=green]
>> Hmm, seems gcc doesn't always handle the <T> form correctly. I would stick
>> with <>.[/color]
>
>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?[/color]

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?
William Xuuu
Guest
 
Posts: n/a
#9: Jul 22 '05

re: linker errors when I use template friends?


comeau@panix.com (Greg Comeau) writes:
[color=blue][color=green]
>>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 ?[/color]
>
> Not sure what you're asking, but perhaps you're looking for
> the long-hand version like a.operator+<int>(b);
>[/color]

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
John Harrison
Guest
 
Posts: n/a
#10: Jul 22 '05

re: linker errors when I use template friends?



"William Xuuu" <abc@abc.abc> wrote in message news:87hdug7yx2.fsf@abc.abc...[color=blue]
> "John Harrison" <john_andronicus@hotmail.com> writes:
>[color=green][color=darkred]
> >> The answer is to tell the compiler that the friend declaration refers[/color][/color][/color]
to a[color=blue][color=green][color=darkred]
> >> template function. You do that by adding '<T>' or '<>' after operator+.
> >>[/color][/color]
>
> Hmm, it works fine by adding <> or <T> as follows.
>[/color]

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


John Harrison
Guest
 
Posts: n/a
#11: Jul 22 '05

re: linker errors when I use template friends?


> >>[color=blue][color=green][color=darkred]
> >>Then I find it's not allowed to use + as:
> >>
> >> a +<int> b;
> >>
> >>So ?[/color]
> >
> > Not sure what you're asking, but perhaps you're looking for
> > the long-hand version like a.operator+<int>(b);
> >[/color]
>
> 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
>[/color]

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


Closed Thread