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 member functions

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





PostPosted: Thu Aug 21, 2003 10:52 am    Post subject: Template member functions Reply with quote



Could someone please explain to me why the following code does not
compile (under GCC 3.2.2)


//--- Code begins here ------------------------


#include <iostream>

class C {

public:

// Templated member function
template<size_t N> void mem_func() const
{ std::cout << data[N] << std::endl; }

int data[10];
};


// Template function at global scope - this is fine
template void helper(const C& c)
{ std::cout << c.data[N] << std::endl; }

/*
// This part will not compile
template static void func(const C& c)
{ c.mem_func<N>(); } // line 23
*/


int main() {

C c;

c.mem_func<0>(); // Call the member function directly
helper<0>(c); // Call the static template function
//func<0>(c); // Cannot compile this
}


//--- Code ends here --------------------------

gcc says...

test.cpp: In function `void func(const C&)':
test.cpp:23: parse error before `)' token


The problem is that the template function 'func' will not compile -
even if I leave the call to it in the main function commented out.

I guess that the compiler is looking for an appropriate instance of
C::mem_func<size_t>, and failing to find it, but I thought template
functions were only instantiated as needed. So, if I don't ever try
to call func, why is the compiler complaining?

Gareth

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Graeme Prentice
Guest





PostPosted: Fri Aug 22, 2003 9:26 am    Post subject: Re: Template member functions Reply with quote



On 21 Aug 2003 06:52:06 -0400, [email]gareth (AT) ebi (DOT) ac.uk[/email] (Gareth Stockwell)
wrote:

Quote:
Could someone please explain to me why the following code does not
compile (under GCC 3.2.2)

nor in GCC 3.2.3

[snip]

Quote:

/*
// This part will not compile
template<size_t N
static void func(const C& c)
{ c.mem_func */

That is a bug in GCC. It doesn't like the mem_func< ... > whatever the
template parameter types, if it's from within a template function.

You can workaround it like this (compiles but untested).

template<size_t N>
static void func(const C& c)
{
void (C::*mp)()const = &C::mem_func<N>;
(c.*mp)();
//c.mem_func<N>();
} // line 23


[snip]

Quote:

The problem is that the template function 'func' will not compile -
even if I leave the call to it in the main function commented out.

I guess that the compiler is looking for an appropriate instance of
C::mem_func<size_t>, and failing to find it, but I thought template
functions were only instantiated as needed. So, if I don't ever try
to call func, why is the compiler complaining?

Template declarations and definitions get parsed when the compiler first
sees them, as much as it is able to, to give the programmer an immediate
indication of errors - just like non template code.

Graeme

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jan Rendek
Guest





PostPosted: Fri Aug 22, 2003 9:46 am    Post subject: Re: Template member functions Reply with quote



Seems like a bug to me.

For an obscure reason the call c.mem_func<N>() raises
a syntax error.

You can bypass that by prefixing the method by the
class it belongs to:

c.C::mem_func<N>()

So the body of your global function becomes:


template<size_t N>
void func(const C& c)
{
c.C::mem_func<N>();
}


Works for me on GCC 3.2.2 on linux Mandrake 8.2

--
Jan Rendek
INRIA Lorraine
r e n d e k @ l o r i a . f r


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Michiel Salters
Guest





PostPosted: Fri Aug 22, 2003 9:59 am    Post subject: Re: Template member functions Reply with quote

[email]gareth (AT) ebi (DOT) ac.uk[/email] (Gareth Stockwell) wrote in message news:<d1b18d21.0308200716.ca1fc55 (AT) posting (DOT) google.com>...
Quote:
Could someone please explain to me why the following code does not
compile (under GCC 3.2.2)

//--- Code begins here ------------------------


#include <iostream

class C {

public:

// Templated member function
template { std::cout << data[N] << std::endl; }

int data[10];
};


// Template function at global scope - this is fine
template void helper(const C& c)
{ std::cout << c.data[N] << std::endl; }

/*
// This part will not compile
template static void func(const C& c)
{ c.mem_func */


int main() {

C c;

c.mem_func<0>(); // Call the member function directly
helper<0>(c); // Call the static template function
//func<0>(c); // Cannot compile this
}


//--- Code ends here --------------------------

gcc says...

test.cpp: In function `void func(const C&)':
test.cpp:23: parse error before `)' token


The problem is that the template function 'func' will not compile -
even if I leave the call to it in the main function commented out.

I guess that the compiler is looking for an appropriate instance of
C::mem_func<size_t>, and failing to find it, but I thought template
functions were only instantiated as needed. So, if I don't ever try
to call func, why is the compiler complaining?

First: a compiler has every right to complain, if the contents of a
template function aren't syntactically correct - even if it's not
instantiated. Imagine the following function

template < int N >
void foo()
{
}
}

May the compiler complain about foo, even when it's not called?

GCC encountered a similar problem here. It needs to determine
if the < > in func(C const&) are paired angle brackets, or
two unrelated operators. It can do so only after looking up
memfunc in C. However, it doesn't, but instead assumes c.memfunc
is an expression. GCC thus expects the full expression to be
c.memfunc without a preceding expression, it generates the error.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Fri Aug 22, 2003 1:03 pm    Post subject: Re: Template member functions Reply with quote

[email]gareth (AT) ebi (DOT) ac.uk[/email] (Gareth Stockwell) writes:

Quote:
Could someone please explain to me why the following code does not
compile (under GCC 3.2.2)


//--- Code begins here ------------------------


#include <iostream

class C {

public:

// Templated member function
template { std::cout << data[N] << std::endl; }

int data[10];
};


// Template function at global scope - this is fine
template void helper(const C& c)
{ std::cout << c.data[N] << std::endl; }

/*
// This part will not compile
template static void func(const C& c)
{ c.mem_func

{ c.template mem_func<N>(); } // line 23

The compiler needs to know 'mem_func' is a template-id in order to
parse the following < correctly; if mem_func is not known to be a
template-id the < is less-than. 'template' lets the compiler know
mem_func is a template-id .


Quote:
*/


int main() {

C c;

c.mem_func<0>(); // Call the member function directly
helper<0>(c); // Call the static template function
//func<0>(c); // Cannot compile this
}
[snip]


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
johnchx
Guest





PostPosted: Fri Aug 22, 2003 1:14 pm    Post subject: Re: Template member functions Reply with quote

[email]gareth (AT) ebi (DOT) ac.uk[/email] (Gareth Stockwell) wrote

Quote:
#include <iostream

class C {

public:

// Templated member function
template { std::cout << data[N] << std::endl; }

int data[10];
};


[snip]

Quote:
template static void func(const C& c)
{ c.mem_func

Gcc wants you to tell it that mem_func is a template, like this:

template<size_t N>
static void func(const C& c)
{ c.template mem_func<N>(); } // added template keyword

I'm not 100% sure whether gcc is right, however. (FWIW, your code
compiles as originally written on comeau-online.) Here's the story:

14.2/4 says:

When the name of a member template specialization appears after . or
-> in a postfix-expression ... and the postfix-expression ...
explicitly depends on a template-parameter (14.6.2), the member
template name must be prefixed by the keyword template. Otherwise
the name is assumed to name a non-template.

(I've elided the language that applies this rule to
nested-name-specifiers, just to make the sentence a little easier to
parse.)

When I read 14.2/4, I get the impression that the postfix-expression
that has to depend on a template-parameter is the same
postfix-expression that encompasses the name of the member template
specialization. In your code, this would be:

c.mem_func<N>

which would appear to depend on N, a template-parameter. So, to my
eye, gcc looks correct.

However...there's reason to believe that others read this differently.
For example, the following (non-normative) note appears in the
resolution of core language issue #30 (accepted into TC1):

[Note: just as is the case with the typename prefix, the
template prefix is allowed in cases where it is not strictly
necessary; i.e., when the expression on the left of the -> or .,
or the nested-name-specifier is not dependent on a
template-parameter. ]

http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#30

which seems to imply that the template keyword is only mandatory if
the postfix-expression to the left of the member access operator is
dependent. I'm not convinced that this is what the standard *says*,
but it does seem like a reasonable interpretation of what it *meant*
to say.

In any event, it's clear that adding the template keyword -- as shown
above -- is legal, so it's probably a good idea to add it if your
compiler needs it.


Quote:
So, if I don't ever try to call func, why is the compiler
complaining?

The compiler should perform basic syntax checking on the template even
if it's not instantiated. It's letting you know that, as written, no
*possible* instantiation could *ever* compile.

HtH!

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Fri Aug 22, 2003 4:28 pm    Post subject: Re: Template member functions Reply with quote

[email]johnchx2 (AT) yahoo (DOT) com[/email] (johnchx) writes:

Quote:
gareth (AT) ebi (DOT) ac.uk (Gareth Stockwell) wrote

#include <iostream

class C {

public:

// Templated member function
template { std::cout << data[N] << std::endl; }

int data[10];
};


[snip]

template static void func(const C& c)
{ c.mem_func

Gcc wants you to tell it that mem_func is a template, like this:

template<size_t N
static void func(const C& c)
{ c.template mem_func
I'm not 100% sure whether gcc is right, however.
[snip]


It's not. It's a bug, fixed in the new parser, (which will probably be
part of gcc 3.4) according to my reading of:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=795


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Kresimir Fresl
Guest





PostPosted: Fri Aug 22, 2003 5:42 pm    Post subject: Re: Template member functions Reply with quote


Gareth Stockwell wrote:

Quote:
Could someone please explain to me why the following code does not
compile (under GCC 3.2.2)

//--- Code begins here ------------------------

#include <iostream

class C {

public:

// Templated member function
template { std::cout << data[N] << std::endl; }

int data[10];
};

// Template function at global scope - this is fine
template void helper(const C& c)
{ std::cout << c.data[N] << std::endl; }

/*
// This part will not compile
template static void func(const C& c)
{ c.mem_func */

int main() {

C c;

c.mem_func<0>(); // Call the member function directly
helper<0>(c); // Call the static template function
//func<0>(c); // Cannot compile this
}

//--- Code ends here --------------------------

If `func' is

template<size_t N>
static void func(const C& c) {
c.template mem_func<N>();
}

code compiles with g++ 3.2.

f.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ali Cehreli
Guest





PostPosted: Sat Aug 23, 2003 3:01 am    Post subject: Re: Template member functions Reply with quote

[email]gareth (AT) ebi (DOT) ac.uk[/email] (Gareth Stockwell) wrote in message
news:<d1b18d21.0308200716.ca1fc55 (AT) posting (DOT) google.com>...

Quote:
Could someone please explain to me why the following code does not
compile (under GCC 3.2.2)

I used g++ 3.2 and got the same problem. Applying a member function
pointer workaround that I used to use for the non-existant Wink gcc-2.96
worked in this case as well.

Quote:

//--- Code begins here ------------------------


#include <iostream

class C {

public:

// Templated member function
template { std::cout << data[N] << std::endl; }

int data[10];
};


// Template function at global scope - this is fine
template void helper(const C& c)
{ std::cout << c.data[N] << std::endl; }

/*
// This part will not compile
template static void func(const C& c)
{ c.mem_func */


int main() {

C c;

c.mem_func<0>(); // Call the member function directly
helper<0>(c); // Call the static template function
//func<0>(c); // Cannot compile this
}


//--- Code ends here --------------------------

gcc says...

test.cpp: In function `void func(const C&)':
test.cpp:23: parse error before `)' token


The problem is that the template function 'func' will not compile -
even if I leave the call to it in the main function commented out.

I guess that the compiler is looking for an appropriate instance of
C::mem_func<size_t>, and failing to find it, but I thought template
functions were only instantiated as needed. So, if I don't ever try
to call func, why is the compiler complaining?

Your explanation makes sense. I would expect the code to compile too.
(I am not a template expert at all :)

Here is my workaround that uses a member function pointer:

// This part DOES compile with g++ 3.2 Smile
template<size_t N>
static void func(const C& c)
{
typedef void (C::*Func)() const;
Func f = &C::mem_func<N>;
(c.*f)();
}

Ali

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
johnchx
Guest





PostPosted: Sat Aug 23, 2003 2:47 pm    Post subject: Re: Template member functions Reply with quote

llewelly <llewelly.at (AT) xmission (DOT) dot.com> wrote

Quote:
I'm not 100% sure whether gcc is right, however.
[snip]

It's not. It's a bug, fixed in the new parser, (which will probably be
part of gcc 3.4) according to my reading of:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=795

Well, I think Nathan Sidwell may be reading too much into the
resolution of DR30. The point of the DR was to specify where it's an
error to add the template keyword extraneously, not to change where
the keyword is required. The DR resolution includes a non-normative
note which characterizes the where the keyword is required in a way
that seems to be inconsistent with the normative text already in the
standard.

I'd agree that the characterization in the note is probably preferable
to what's in the normative text, but we may need an additional DR to
make it properly legal.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Richard Smith
Guest





PostPosted: Thu Aug 28, 2003 8:08 pm    Post subject: Re: Template member functions Reply with quote

Gareth Stockwell wrote:

Quote:
class C {
public:
// Templated member function
template<size_t N> void mem_func() const
{ std::cout << data[N] << std::endl; }

int data[10];
};

// This part will not compile
template static void func(const C& c)
{ c.mem_func

I think this code is legal, howeer gcc does indeed reject
it. To make gcc happy, change the last line to read

{ c.template mem_func<N>(); }

The extra template keyword is to tell the compiler that
mem_func is a template function, and thus to parse the '<'
as the start of a list of template arguments rather than a
less-than comparision operator. For a good description of
this, see Vandervoorde & Josuttis' book "C++ Templates: The
Complete Guide".

The reason I don't think the "template" is actually
necessary, is that the expression 'c' is not dependent on a
template parameter.

--
Richard Smith

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jeff Mirwaisi
Guest





PostPosted: Sun Aug 31, 2003 8:00 am    Post subject: Re: Template member functions Reply with quote

//A simplified axample
struct S{template <int N> void f() {}};

//clearly indicated that template is required by 14.2, par 4
template <typename T> void test(T& t) {t.template f<0>();}

//14.2 para 4 seems to indicate that template is needed here as well
template <int N> void test(S& t) {t.template f<N>();}

// even though "the postfix-expression or qualified-id explicitly depends
// on a template-parameter" compiles fine under comeau

template <int N> void test(S& t) {t.f<N>();}


I believe comeau is in error above, but unfortunately the example
provided in the standard only demonstrates a scenario where the tpe
itself is a template parameter, not where the template parameter for the
template method specialization is explicitly dependant on a template
parameter

class X {
public:
template<size_t> X* alloc();
template<size_t> static X* adjust();
};
template<class T> void f(T* p)
{
T* p1 = p->alloc<200>();
// ill-formed: < means less than

T* p2 = p->template alloc<200>();
// OK: < starts template argument list

T::adjust<100>();
// ill-formed: < means less than

T::template adjust<100>();
// OK: < starts explicit qualification
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
johnchx
Guest





PostPosted: Wed Sep 03, 2003 12:50 am    Post subject: Re: Template member functions Reply with quote

Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> wrote

Quote:
Jeff Mirwaisi wrote:
//A simplified axample
struct S{template <int N> void f() {}};

//clearly indicated that template is required by 14.2, par 4
template <typename T> void test(T& t) {t.template f<0>();}

//14.2 para 4 seems to indicate that template is needed here as well
template <int N> void test(S& t) {t.template f<N>();}

// even though "the postfix-expression or qualified-id explicitly depends
// on a template-parameter" compiles fine under comeau

template <int N> void test(S& t) {t.f<N>();}
snip

The postfix-expression is "t" and it clearly doesn't depend on a
template parameter.


No, "t" is *a* postfix-expression, but it is not the
postifx-expression referred to in 14.2/4. That paragraph says:

When the name of a member template specialization appears after
. or -> in a postfix-expression...

Note the "in." The paragraph is speaking of a postfix-expression
which encompasses both the name of the member template and the member
access operator.

This might be an error in the standard (I tend to suspect that it is),
but that's what it seems to say at the moment...unless there's another
way to read this paragraph that I'm overlooking, which is always
possible. :-)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Wed Sep 03, 2003 9:44 pm    Post subject: Re: Template member functions Reply with quote

In article <4fb4137d.0309020701.445d01bd (AT) posting (DOT) google.com>,
johnchx wrote:
Quote:
Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> wrote

Jeff Mirwaisi wrote:
//A simplified axample
struct S{template <int N> void f() {}};

//clearly indicated that template is required by 14.2, par 4
template <typename T> void test(T& t) {t.template f<0>();}

//14.2 para 4 seems to indicate that template is needed here as well
template <int N> void test(S& t) {t.template f<N>();}

// even though "the postfix-expression or qualified-id explicitly
// depends on a template-parameter" compiles fine under comeau

template <int N> void test(S& t) {t.f<N>();}
snip

The postfix-expression is "t" and it clearly doesn't depend on a
template parameter.


No, "t" is *a* postfix-expression, but it is not the
postifx-expression referred to in 14.2/4.

Oops. Yes, I see that the postfix-expression is "t.f<N>" which
obviously does depend on the template-parameter N.

<snip>
Quote:
This might be an error in the standard (I tend to suspect that it is),
but that's what it seems to say at the moment...unless there's another
way to read this paragraph that I'm overlooking, which is always
possible. Smile

I can't see another interpretation that doesn't depend on assuming the
wording is a mistake. It seems to me to be sensible to replace "the
postfix-expression or qualified-id" with "the postfix-expression
preceding the . or -> or the nested-name-specifier", but that's a bit
of a stretch. Yet that does seem to be what has been implemented.

[ 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.