 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Gareth Stockwell Guest
|
Posted: Thu Aug 21, 2003 10:52 am Post subject: Template member functions |
|
|
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
|
Posted: Fri Aug 22, 2003 9:26 am Post subject: Re: Template member functions |
|
|
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
|
Posted: Fri Aug 22, 2003 9:46 am Post subject: Re: Template member functions |
|
|
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
|
Posted: Fri Aug 22, 2003 9:59 am Post subject: Re: Template member functions |
|
|
[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
|
Posted: Fri Aug 22, 2003 1:03 pm Post subject: Re: Template member functions |
|
|
[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
|
Posted: Fri Aug 22, 2003 1:14 pm Post subject: Re: Template member functions |
|
|
[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
|
Posted: Fri Aug 22, 2003 4:28 pm Post subject: Re: Template member functions |
|
|
[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
|
Posted: Fri Aug 22, 2003 5:42 pm Post subject: Re: Template member functions |
|
|
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
|
Posted: Sat Aug 23, 2003 3:01 am Post subject: Re: Template member functions |
|
|
[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 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
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
|
Posted: Sat Aug 23, 2003 2:47 pm Post subject: Re: Template member functions |
|
|
llewelly <llewelly.at (AT) xmission (DOT) dot.com> wrote
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
|
Posted: Thu Aug 28, 2003 8:08 pm Post subject: Re: Template member functions |
|
|
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
|
Posted: Sun Aug 31, 2003 8:00 am Post subject: Re: Template member functions |
|
|
//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
|
Posted: Wed Sep 03, 2003 12:50 am Post subject: Re: Template member functions |
|
|
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
|
Posted: Wed Sep 03, 2003 9:44 pm Post subject: Re: Template member functions |
|
|
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.
|
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 |
|
 |
|
|
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
|
|