 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Frank Guest
|
Posted: Sat Jan 15, 2005 3:52 am Post subject: Template, friend and unresolved references |
|
|
I have the following template class ( simplified ) in a point.h file:
template <typename T, unsigned short DIM=3>
class Point
{
public:
// subscript
T operator [] (int sub);
// formatted stream I/O
friend std::ostream& operator << (std::ostream& os, const Point&
p);
private:
T data_[DIM];
};
template
inline std::ostream& operator << (std::ostream& os, const
Point
{
for (int i=0; i<DIM-1; i++)
os << p.data_[i] << " ";
os << p.data_[DIM-1];
return os;
}
in a .cpp file I have:
void foo()
{
....
ostrstream os;
Point
.....
os << pt << ends;
}
When I build a dll with this function in it, I get unresolved
externals for the << operator. If I remove the friend declaration and
instead use the [] operator in the operator << method it all builds
OK.
Can anyone please shed some light on why?
(Using VStudio.Net 2003 )
Thanks
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Sun Jan 16, 2005 4:12 am Post subject: Re: Template, friend and unresolved references |
|
|
Frank <opcode (AT) telus (DOT) net> writes:
| Quote: | template <typename T, unsigned short DIM=3
class Point
{
public:
// subscript
T operator [] (int sub);
// formatted stream I/O
friend std::ostream& operator << (std::ostream& os, const Point&
p);
|
This declares a non-template function, and declares it to be a friend.
| Quote: | private:
T data_[DIM];
};
template
inline std::ostream& operator << (std::ostream& os, const
Point
|
This defines a function template. It is not related to the
non-template function you have just declared.
| Quote: | ostrstream os;
Point<double,3> pt;
....
os << pt << ends;
|
Here, the compiler finds two equally good matches; one is the
non-template function, the other a specialization of the function
template. In this situation, the non-template function is
picked. Since you don't provide a definition of that function, you end
up with the linker error.
The solution is to not declare the non-template function. Instead, do
template
class Point;
template <typename T, unsigned short DIM=3>
std::ostream& operator << (std::ostream&, const Point
template <typename T, unsigned short DIM=3>
class Point
{
public:
// subscript
T operator [] (int sub);
// formatted stream I/O
friend std::ostream& operator << <>(std::ostream&, const Point&);
private:
T data_[DIM];
};
Note the added "<>" in the friend declaration. It causes a
specialization of the previsouly declared function template to be
declared a friend.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Guest
|
Posted: Tue Jan 18, 2005 11:20 pm Post subject: Re: Template, friend and unresolved references |
|
|
On 15 Jan 2005 23:12:58 -0500, Thomas Maeder <maeder (AT) glue (DOT) ch> wrote:
.... snip ....
| Quote: |
The solution is to not declare the non-template function. Instead, do
template <typename T, unsigned short DIM=3
class Point;
template
std::ostream& operator << (std::ostream&, const Point
template <typename T, unsigned short DIM=3
class Point
|
When I make the changes as suggested I get a redefinition of default
parameter warning for parmeter 2 ( ie DIM=3 ). Removing it fixes the
problem but I'm wondering what the rule is for forward declaring
default parameters.
| Quote: | {
public:
// subscript
T operator [] (int sub);
// formatted stream I/O
friend std::ostream& operator << <>(std::ostream&, const Point&);
private:
T data_[DIM];
};
Note the added "<>" in the friend declaration. It causes a
specialization of the previsouly declared function template to be
declared a friend.
|
Many thanks for the explanation.
Frank
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Krügler (ne Spange Guest
|
Posted: Wed Jan 19, 2005 11:53 pm Post subject: Re: Template, friend and unresolved references |
|
|
Hello Frank,
Frank schrieb:
| Quote: | The solution is to not declare the non-template function. Instead, do
template <typename T, unsigned short DIM=3
class Point;
template
std::ostream& operator << (std::ostream&, const Point
template <typename T, unsigned short DIM=3
class Point
When I make the changes as suggested I get a redefinition of default
parameter warning for parmeter 2 ( ie DIM=3 ). Removing it fixes the
problem but I'm wondering what the rule is for forward declaring
default parameters.
Your fixes are necessary, because the proposed code contains some minor |
errors:
1) According to 14.1/p. 9, function template declarations/definitions
are not allowed to specify
default template arguments (which is actually an unnecessary constraint
and just due to historical
reasons - I strongly assume, that there exist a defect report for this).
This limits the declaration
of the stream inserter function to
template
std::ostream& operator << (std::ostream&, const Point
Similar to the rules for default parameters of functions, 14.1/p.12
says that two declarations of the
same class template shall not not provide template default arguments for
corresponding template
paramters, thus the definition of Point has to written as
template <typename T, unsigned short DIM>
class Point {
...
};
Greetings from Bremen,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Guest
|
Posted: Thu Jan 20, 2005 8:09 pm Post subject: Re: Template, friend and unresolved references |
|
|
Thank-you Daniel.
I have a follow on problem similar to the original except I'm trying
to declare friend operator * instead of operator <<
Following the explanation from Thomas I setup the following:
// forward declares
template
class Vector;
// template function to multply two vectors
template <typename T, unsigned short DIM>
Vector<T,DIM> operator * (const Vector<T,DIM>& v1, const
Vector<T,DIM>& v2);
template <typename T, unsigned short DIM=3>
class Vector
{
public:
// subscript
T operator [] (int sub);
// attempt 1 - compiles but unresolved external ref (as in OP)
// friend Vector<T,DIM> operator * (const Vector<T,DIM>& v1, const
Vector<T,DIM>& v2);
// attempt 2 -as explained by Thomas - failled to compile complaining
about the <>
// friend Vector<T,DIM> operator * <> (const Vector<T,DIM>& v1,
const Vector<T,DIM>& v2);
// attempt 3 - works
template <typename T, unsigned short DIM>
friend Vector<T,DIM> operator * <> (const Vector<T,DIM>& v1, const
Vector<T,DIM>& v2);
private:
T data_[DIM];
};
template <typename T, unsigned short DIM>
inline Vector<T,DIM> operator * (const Vector<T,DIM>&v1, const
Vector<T,DIM>& v2)
{
.... snip
}
all of this in a .h file ( using VS.Net 2003 )
attempt 1 fails as explained by Thomas
attempt 2 is similar in style to solution for my OP.
Why does it work with operator << and not operator *?
Why does attempt 3 work? ( ie what difference does adding the
"template
make?
Thanks for any explanation.
Frank
On 19 Jan 2005 18:53:40 -0500, "Daniel Krügler (ne Spangenberg)"
<dsp (AT) bdal (DOT) de> wrote:
| Quote: | Hello Frank,
Frank schrieb:
The solution is to not declare the non-template function. Instead, do
template <typename T, unsigned short DIM=3
class Point;
template
std::ostream& operator << (std::ostream&, const Point
template <typename T, unsigned short DIM=3
class Point
When I make the changes as suggested I get a redefinition of default
parameter warning for parmeter 2 ( ie DIM=3 ). Removing it fixes the
problem but I'm wondering what the rule is for forward declaring
default parameters.
Your fixes are necessary, because the proposed code contains some minor
errors:
1) According to 14.1/p. 9, function template declarations/definitions
are not allowed to specify
default template arguments (which is actually an unnecessary constraint
and just due to historical
reasons - I strongly assume, that there exist a defect report for this).
This limits the declaration
of the stream inserter function to
template
std::ostream& operator << (std::ostream&, const Point
Similar to the rules for default parameters of functions, 14.1/p.12
says that two declarations of the
same class template shall not not provide template default arguments for
corresponding template
paramters, thus the definition of Point has to written as
template
class Point {
..
};
Greetings from Bremen,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Fri Jan 21, 2005 10:33 am Post subject: Re: Template, friend and unresolved references |
|
|
Frank <opcode (AT) telus (DOT) net> writes:
| Quote: | // forward declares
template <typename T, unsigned short DIM
class Vector;
// template function to multply two vectors
template
Vector
Vector<T,DIM>& v2);
template <typename T, unsigned short DIM=3
class Vector
{
public:
// subscript
T operator [] (int sub);
|
[snip]
| Quote: | // attempt 2 -as explained by Thomas - failled to compile complaining
about the
// friend Vector
const Vector<T,DIM>& v2);
|
This should compile. Your compiler seems to have a bug.
| Quote: | // attempt 3 - works
template <typename T, unsigned short DIM
friend Vector
Vector<T,DIM>& v2);
|
This shouldn't work since the names T and DIM are already used for
something different. More, you have to remove the "<>" since you are
you are not making one specialization a friend but *all*
specializations.
Is the code you posted the code you tried?
[trimmed a lot of unnecessary quotes]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Guest
|
Posted: Sat Jan 22, 2005 11:33 am Post subject: Re: Template, friend and unresolved references |
|
|
On 21 Jan 2005 05:33:25 -0500, Thomas Maeder <maeder (AT) glue (DOT) ch> wrote:
| Quote: | Frank <opcode (AT) telus (DOT) net> writes:
// forward declares
template <typename T, unsigned short DIM
class Vector;
// template function to multply two vectors
template
Vector
Vector<T,DIM>& v2);
template <typename T, unsigned short DIM=3
class Vector
{
public:
// subscript
T operator [] (int sub);
[snip]
// attempt 2 -as explained by Thomas - failled to compile complaining
about the
// friend Vector
const Vector<T,DIM>& v2);
This should compile. Your compiler seems to have a bug.
|
Microsoft VS.Net 2003
| Quote: |
// attempt 3 - works
template <typename T, unsigned short DIM
friend Vector
Vector<T,DIM>& v2);
This shouldn't work since the names T and DIM are already used for
something different. More, you have to remove the "<>" since you are
you are not making one specialization a friend but *all*
specializations.
|
My apologies! I did remove the <> and the <T,DIM> ( Leaving the <>
in caused the same compile error. The <T,DIM> in the post came from
copying from the forward declare )
declaration that works is:
template <typename T, unsigned short DIM>
friend Vector operator * (const Vector& v1, const Vector& v2);
this causes unresolved externals:
friend Vector<T,DIM> operator * (const Vector<T,DIM>&v1, const
Vector<T,DIM>& v2);
this causes compiler errors
friend Vector<T,DIM> operator * <> (const Vector<T,DIM>&v1, const
Vector<T,DIM>& v2);
this causes fatal error C1001: INTERNAL COMPILER ERROR
template <typename T, unsigned short DIM>
friend Vector<T,DIM> operator * (const Vector<T,DIM>&v1, const
Vector<T,DIM>& v2);
I've read up on friends in the Vandervoode-Josuttis template book to
try and understand the rules so I don't code it by trial and error,
but I'm still mystified - perhaps because what should work might be a
compiler bug.
Your help is appreciated.
Frank
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Seungbeom Kim Guest
|
Posted: Sun Jan 23, 2005 2:50 am Post subject: Re: Template, friend and unresolved references |
|
|
Thomas Maeder wrote:
| Quote: | template <typename T, unsigned short DIM=3
class Point
{
public:
// formatted stream I/O
friend std::ostream& operator << (std::ostream& os, const Point& p);
This declares a non-template function, and declares it to be a friend.
};
|
I don't understand how this can be a non-template function, because it
has a parameter of type const Point
template arguments, and consequently I don't see how it can differ from
the version below. Could you explain this?
| Quote: | template <typename T, unsigned short DIM
inline std::ostream& operator << (std::ostream& os, const Point
This defines a function template. It is not related to the
non-template function you have just declared.
|
--
Seungbeom Kim
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Sun Jan 23, 2005 10:17 am Post subject: Re: Template, friend and unresolved references |
|
|
Seungbeom Kim wrote:
| Quote: | I don't understand how this can be a non-template function
|
Function templates can only be declared using the
template<template_args> return_type name(function_ args);
syntax. Otherwise, you are simply declaring a family of
overloaded functions taking different argument types, just as
if you had written something like
void f(vector<int>);
void f(vector<char>);
void f(vector<double>);
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Sun Jan 23, 2005 10:17 am Post subject: Re: Template, friend and unresolved references |
|
|
Seungbeom Kim <musiphil (AT) bawi (DOT) org> writes:
| Quote: | template <typename T, unsigned short DIM=3
class Point
{
public:
// formatted stream I/O
friend std::ostream& operator << (std::ostream& os, const Point& p);
This declares a non-template function, and declares it to be a friend.
};
I don't understand how this can be a non-template function, because it
has a parameter of type const Point
template arguments, and consequently I don't see how it can differ from
the version below. Could you explain this?
|
The declared function is not a template because its declaration isn't
preceded by the keyword template.
What the declaration means is: should a (non-template) function
std::ostream& operator << (std::ostream& os, const Point
(for the T and DIM we are currently instantiating Point with) be
defined somewhere, that definition can access the private and
protected parts of the specialization Point<T,DIM>.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|