C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Template, friend and unresolved references

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Frank
Guest





PostPosted: Sat Jan 15, 2005 3:52 am    Post subject: Template, friend and unresolved references Reply with quote




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





PostPosted: Sun Jan 16, 2005 4:12 am    Post subject: Re: Template, friend and unresolved references Reply with quote



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





PostPosted: Tue Jan 18, 2005 11:20 pm    Post subject: Re: Template, friend and unresolved references Reply with quote



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





PostPosted: Wed Jan 19, 2005 11:53 pm    Post subject: Re: Template, friend and unresolved references Reply with quote

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





PostPosted: Thu Jan 20, 2005 8:09 pm    Post subject: Re: Template, friend and unresolved references Reply with quote

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





PostPosted: Fri Jan 21, 2005 10:33 am    Post subject: Re: Template, friend and unresolved references Reply with quote

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





PostPosted: Sat Jan 22, 2005 11:33 am    Post subject: Re: Template, friend and unresolved references Reply with quote

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





PostPosted: Sun Jan 23, 2005 2:50 am    Post subject: Re: Template, friend and unresolved references Reply with quote

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





PostPosted: Sun Jan 23, 2005 10:17 am    Post subject: Re: Template, friend and unresolved references Reply with quote

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





PostPosted: Sun Jan 23, 2005 10:17 am    Post subject: Re: Template, friend and unresolved references Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.