 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Josef Svitak Guest
|
Posted: Sat Aug 26, 2006 4:25 pm Post subject: friend function as template parameter |
|
|
Is this C98-legal C++?
template< void (*func)(int) > class A {};
class B {
friend void someFunc(int);
A< someFunc > a_;
}
It compiles with g++3.2 but not with g++4.1.1. Was wondering if they
have just gotten more strict with the standard.
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 Tutone Guest
|
Posted: Sat Aug 26, 2006 8:37 pm Post subject: Re: friend function as template parameter |
|
|
Josef Svitak wrote:
| Quote: | Is this C98-legal C++?
template< void (*func)(int) > class A {};
class B {
friend void someFunc(int);
A< someFunc > a_;
}
It compiles with g++3.2 but not with g++4.1.1. Was wondering if they
have just gotten more strict with the standard.
|
Comeau says your code is not legal (even if you add the missing
semicolon to the end of your class). It says that this code is legal,
though:
template< void (*func)(int) > class A {};
void someFunc(int); // this line is new
class B {
friend void someFunc(int);
A< someFunc > a_;
};
I don't know why the friend declaration is insufficient - some language
lawyer will have to jump in and explain, but I think gcc 4.1.1 has it
right in this instance.
Best regards,
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Jiang Guest
|
Posted: Sat Aug 26, 2006 9:40 pm Post subject: Re: friend function as template parameter |
|
|
Josef Svitak wrote:
| Quote: | Is this C98-legal C++?
template< void (*func)(int) > class A {};
class B {
friend void someFunc(int);
A< someFunc > a_;
}
It compiles with g++3.2 but not with g++4.1.1. Was wondering if they
have just gotten more strict with the standard.
|
The above code is ill-formed because local type can not
be used as a template-argument for a template type-parameter.
But not all compilers enforce this rule.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Thomas Tutone Guest
|
Posted: Sun Aug 27, 2006 4:46 am Post subject: Re: friend function as template parameter |
|
|
Jiang wrote:
| Quote: | Josef Svitak wrote:
Is this C98-legal C++?
template< void (*func)(int) > class A {};
class B {
friend void someFunc(int);
A< someFunc > a_;
}
It compiles with g++3.2 but not with g++4.1.1. Was wondering if they
have just gotten more strict with the standard.
The above code is ill-formed because local type can not
be used as a template-argument for a template type-parameter.
|
Not true. The rule is that a class or struct local to a function
cannot be used as a template argument, but a class or struct that is
simply local to another class - i.e., a subclass - is a perfectly valid
template argument. If the rule were otherwise, the following would be
ill-formed:
template< typename T > class A {};
class B {
class C {};
A< C > a_;
};
But as far as I know, that code is fine.
Best regards,
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Gennaro Prota Guest
|
Posted: Sun Aug 27, 2006 7:39 am Post subject: Re: friend function as template parameter |
|
|
On 26 Aug 2006 11:37:21 -0400, "Thomas Tutone"
<Thomas8675309 (AT) yahoo (DOT) com> wrote:
| Quote: | Josef Svitak wrote:
Is this C98-legal C++?
template< void (*func)(int) > class A {};
class B {
friend void someFunc(int);
A< someFunc > a_;
}
It compiles with g++3.2 but not with g++4.1.1. Was wondering if they
have just gotten more strict with the standard.
Comeau says your code is not legal (even if you add the missing
semicolon to the end of your class). It says that this code is legal,
though:
template< void (*func)(int) > class A {};
void someFunc(int); // this line is new
class B {
friend void someFunc(int);
A< someFunc > a_;
};
I don't know why the friend declaration is insufficient - some language
lawyer will have to jump in and explain, but I think gcc 4.1.1 has it
right in this instance.
|
I don't have my copy of the standard at hand but I'm sure it says
explicitly (somewhere in clause 7) that the friend declaration is not
enough in itself to make the friend function name reachable by
ordinary name lookup; that until you provide a matching declaration in
the innermost enclosing namespace (which is where the friend function
is assumed to be when seeing the friend declaration).
--
Gennaro Prota
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Jiang Guest
|
Posted: Sun Aug 27, 2006 5:35 pm Post subject: Re: friend function as template parameter |
|
|
Thomas Tutone wrote:
| Quote: | Josef Svitak wrote:
Is this C98-legal C++?
template< void (*func)(int) > class A {};
class B {
friend void someFunc(int);
A< someFunc > a_;
}
It compiles with g++3.2 but not with g++4.1.1. Was wondering if they
have just gotten more strict with the standard.
Comeau says your code is not legal (even if you add the missing
semicolon to the end of your class).
|
The code is not legal because according to 14.6.5/p1,
" Friend classes or functions can be declared within a
class template. When a template is instantiated, the
names of its friends are treated as if the specialization
had been explicitly declared at its point of instantiation."
And the problem is where is the declaration should be.
In 3.3/p3, we know that
" The names declared by a declaration are introduced
into the scope in which the declaration occurs, except
that the presence of a friend specifier, [snip]."
And in 3.3.1/p6, we have
" friend declarations refer to functions or classes that
are members of the nearest enclosing namespace,
but they do not introduce new names into that namespace."
In OP's example, someFunc has not been declared before
the friend declaration, so the compiler supposes there will
be a file scope declaration according to the above rules.
And the compiler will complain if it can not find the file
scope declaration.
| Quote: | It says that this code is legal,
though:
template< void (*func)(int) > class A {};
void someFunc(int); // this line is new
class B {
friend void someFunc(int);
A< someFunc > a_;
};
|
Add the file scope declaration then the code is well-formed.
| Quote: |
I don't know why the friend declaration is insufficient - some language
lawyer will have to jump in and explain, but I think gcc 4.1.1 has it
right in this instance.
|
Only friend declaration is not sufficient because it refers to
functions or classes that are members of the nearest
enclosing namespace, but it does not introduce new name
into that namespace.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Jiang Guest
|
Posted: Sun Aug 27, 2006 7:50 pm Post subject: Re: friend function as template parameter |
|
|
Thomas Tutone wrote:
| Quote: | Jiang wrote:
The above code is ill-formed because local type can not
be used as a template-argument for a template type-parameter.
Not true. The rule is that a class or struct local to a function
cannot be used as a template argument, but a class or struct that is
simply local to another class - i.e., a subclass - is a perfectly valid
template argument.
|
Yes, you are correct, and I apologize for the confusion I've made.
For some reason I misinterpreted the friend local scope and local
type. I've posted another message in the same thread, and hope
it explains this issue a little bit clearer.
Thank you for your correction.
Best regards,
Jiang
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Alf P. Steinbach Guest
|
Posted: Mon Aug 28, 2006 1:09 am Post subject: Re: friend function as template parameter |
|
|
* Gennaro Prota:
| Quote: |
I don't have my copy of the standard at hand but I'm sure it says
explicitly (somewhere in clause 7) that the friend declaratio is not
enough in itself to make the friend function name reachable by
ordinary name lookup; that until you provide a matching declaration in
the innermost enclosing namespace (which is where the friend function
is assumed to be when seeing the friend declaration).
|
I assume §7.3.2.1/3 is the most relevant paragraph; it states that "The
name of the friend is not found by simple name lookup until a matching
declaration is provided in that namespace scope (either before or after
the class declaration granting friendship)". Where "that namespace"
refers to the innermost enclosing namespace.
It seems to boil down to whether
struct S
{
friend void foo();
void bah() const { foo(); }
};
void foo() {}
int main() { S().bah(); }
is valid or not.
And the way I interpret §7.3.2.1/3 it's not valid, although e.g. MSVC
7.1 compiles the code with no warnings or errors (Comeau Online
complains, though).
On the other hand, I think it /should/ be valid.
Having all these mixed states with names that are somewhat-but-not-quite
declared IMHO just introduces needless confusion.
Also, the case of a friend function /defined/ in the class is extremely
counter-intuitive, as the following illustrates:
struct S
{
friend void foo() {}
void bah() const { foo(); }
};
int main() { S().bah(); }
Even MSVC chokes on the foo call, stating that foo is inaccessible.
Who (other than a language lawyer) would have imagined this was invalid?
Disclaimer: opinion formed on a less than complete understanding. ;-)
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Gennaro Prota Guest
|
Posted: Mon Aug 28, 2006 8:17 am Post subject: Re: friend function as template parameter |
|
|
On 27 Aug 2006 16:09:33 -0400, "Alf P. Steinbach" <alfps (AT) start (DOT) no>
wrote:
| Quote: | Even MSVC chokes on the foo call, stating that foo is inaccessible.
|
Even?? :-)
| Quote: | Who (other than a language lawyer) would have imagined this was invalid?
|
I'm sure you just failed to "recognize" the issue; it's just the
well-known committee decision to remove friend name injection. The
only idiom that made good use of it was found to be the Barton-Nackman
trick, and ADL rules were tweaked to make it still legal despite the
removal of friend name injection.
--
Gennaro Prota
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Josef Svitak Guest
|
Posted: Wed Aug 30, 2006 4:41 am Post subject: Re: friend function as template parameter |
|
|
Thomas Tutone wrote:
| Quote: | template< void (*func)(int) > class A {};
void someFunc(int); // this line is new
class B {
friend void someFunc(int);
A< someFunc > a_;
};
I don't know why the friend declaration is insufficient - some language
lawyer will have to jump in and explain, but I think gcc 4.1.1 has it
right in this instance.
|
Right. And thanks to the lively discussion, I not only know how to fix
it but why it worked in earlier versions of gcc (from the man page for
g++ 4.1.1):
"-ffriend-injection
Inject friend functions into the enclosing namespace, so that they
are visible outside the scope of the class in which they are
declared. Friend functions were documented to work this way in the
old Annotated C++ Reference Manual, and versions of G++ before 4.1
always worked that way. However, in ISO C++ a friend function
which is not declared in an enclosing scope can only be found using
argument dependent lookup. This option causes friends to be
injected as they were in earlier releases.
This option is for compatibility, and may be removed in a future
release of G++.
"
This discussion really did help my understanding immensely. Thanks again.
joe
[ 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
|
|