Template Friend Function, GCC and C++ FAQ Lite

C

Christophe Barbe

I posted a few days ago about the same problem but was not very clear. So
here is my second take at it.

Basically with GCC 3.3.2, I can't compile the example [34.15] from the
C++ FAQ Lite available online at
http://www.parashift.com/c++-faq-lite/containers-and-templates.html#faq-34.15

Below are the two files that I compile with
g++ foo.cpp -o foo
or
g++ -DMAKE_GCC_HAPPY foo.cpp -o foo

Gcc is happy when I use -DMAKE_GCC_HAPPY but if I don't it says:

$ g++ foo.cpp -o foo
In file included from foo.cpp:1:
foo.h:17: warning: friend declaration `Foo<T> operator+(const Foo<T>&, const
Foo<T>&)' declares a non-template function
foo.h:17: 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
foo.h:18: warning: friend declaration `std::eek:stream& operator<<(std::eek:stream&,
const Foo<T>&)' declares a non-template function
/tmp/ccYOJ2nR.o(.text+0x5c): In function `main':
: undefined reference to `operator+(Foo<int> const&, Foo<int> const&)'
/tmp/ccYOJ2nR.o(.text+0x70): In function `main':
: undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Foo<int> const&)'
collect2: ld returned 1 exit status

My understanding is that defining the friend functions before the class is
not enough to make obvious to the compiler that they are template
functions.

Any ideas?

Thanks,
Christophe

---- foo.cpp ----
#include "foo.h"
#include <string>
#include <iostream>

using namespace std;

int main()
{
Foo<int> lhs(1);
Foo<int> rhs(2);
Foo<int> result = lhs + rhs;
cout << result << endl;
}
---- end of foo.cpp ----

---- foo.h ----
#include <iostream>

#ifdef MAKE_GCC_HAPPY
#define __TFS__ <>
#else
#define __TFS__
#endif

template<typename T> class Foo; // pre-declare the template class itself
template<typename T> Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
template<typename T> std::eek:stream& operator<< (std::eek:stream& o, const Foo<T>& x);

template<typename T>
class Foo {
public:
Foo(const T& value = T());
friend Foo<T> operator+ __TFS__ (const Foo<T>& lhs, const Foo<T>& rhs);
friend std::eek:stream& operator<< __TFS__ (std::eek:stream& o, const Foo<T>& x);
private:
T value_;
};

template<typename T>
Foo<T>::Foo(const T& value) : value_(value)
{ }

template<typename T>
Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs)
{
return Foo<T>(lhs.value_ + rhs.value_);
}

template<typename T>
std::eek:stream& operator<< (std::eek:stream& o, const Foo<T>& x)
{
return o << x.value_;
}


---- end of foo.h ----
 
R

Rolf Magnus

Christophe said:
I posted a few days ago about the same problem but was not very clear.
So here is my second take at it.

Basically with GCC 3.3.2, I can't compile the example [34.15] from the
C++ FAQ Lite available online at
http://www.parashift.com/c++-faq-lite containers-and-templates.html#faq-34.15

Below are the two files that I compile with
g++ foo.cpp -o foo
or
g++ -DMAKE_GCC_HAPPY foo.cpp -o foo

Gcc is happy when I use -DMAKE_GCC_HAPPY but if I don't it says:

$ g++ foo.cpp -o foo
In file included from foo.cpp:1:
foo.h:17: warning: friend declaration `Foo<T> operator+(const Foo<T>&,
const
Foo<T>&)' declares a non-template function
foo.h:17: 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
foo.h:18: warning: friend declaration `std::eek:stream&
operator<<(std::eek:stream&,
const Foo<T>&)' declares a non-template function
/tmp/ccYOJ2nR.o(.text+0x5c): In function `main':
: undefined reference to `operator+(Foo<int> const&, Foo<int> const&)'
/tmp/ccYOJ2nR.o(.text+0x70): In function `main':
: undefined reference to `operator<<(std::basic_ostream<char,
: std::char_traits<char> >&, Foo<int> const&)'
collect2: ld returned 1 exit status

My understanding is that defining the friend functions before the
class is not enough to make obvious to the compiler that they are
template functions.

Any ideas?

gcc is right. In chapter C.13.2 of TC++PL3, Stroustrup writes an
example:


========================= begin quote ================================

template<class T> class Matrix;

template<class T> class Vector {
T v[4];
public:
friend Vector operator*<>(const Matrix<T>&, const Vector&);
// ...
};

template<class T> class Matrix {
Vector<T> v[4];
public:
friend Vector<T> operator*<>(const Matrix&, const Vector<T>&);
// ...
};

Te <> after the name of the friend function is needed to make clear that
the friend is a template function. Without the <>, a non-template
function would be assumed.

========================= end quote ==================================
 
C

Christophe Barbe

gcc is right. In chapter C.13.2 of TC++PL3, Stroustrup writes an
example:

Thanks.
So VC++ is wrong (which is not really a surprise) and the faq has to be
updated. For the former I can do nothing, I will contact the author of the
C++ FAQ lite.

Thanks again,
Christophe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,129
Latest member
FastBurnketo
Top