 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Michael Mehlich Guest
|
Posted: Fri Oct 21, 2005 5:14 am Post subject: Dependent names |
|
|
Hello,
I'm trying to understand the notion of "dependent name" in C++
as defined by the ISO standard.
However, I could not derive the proper semantics for the following
program:
#include <iostream>
int foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { };
int baz() {
foo(bar(0));
};
};
int foo(int) { std::cout << "intn"; }
int main() {
X
x.baz();
};
Section 14.6.2., paragraph 1 of the standard suggests
strongly that the use of bar in the member function baz
does not denote a dependent name.
On the other hand, section 14.6.2.2, paragraph 3 could
suggest that bar is an identifier that is declared with
a dependent type (if one considers the type of the implicit
object parameter X<T>& as a participant in bar's type).
As such, bar seems to be a non-dependent name that is a type
dependent expression...
The three C++ compilers I have access to all consider bar(0)
as a type-dependent expression, resulting in the use of foo
in the member function baz being a dependent name.
This is the case even if bar is declared to be a static
member function.
Is this behavior correct?
How do I derive the answer from the standard?
If I change the class template X to
template<typename T> struct X {
int bar(unsigned int) { };
int bar(T) { };
int baz() {
foo(bar(0));
};
};
the above-mentioned compilers will resolve bar in baz
to call the member function int bar(T).
Thus, bar seems to be considered to be a dependent name, thus
violating 14.6.2., paragraph 1.
However, if bar in baz is not a dependent name, then it must
be bound during template definition, requiring that int bar(T)
is ignored (as dependent on the template parameter), and therefore
bar in baz is bound to int bar(unsigned int)...
Puzzled,
Michael
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Anthony Williams Guest
|
Posted: Fri Oct 21, 2005 2:47 pm Post subject: Re: Dependent names |
|
|
[email]michael (AT) mehlich (DOT) com[/email] (Michael Mehlich) writes:
| Quote: | #include <iostream
int foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { };
int baz() {
foo(bar(0));
};
};
int foo(int) { std::cout << "intn"; }
int main() {
X
x.baz();
};
Section 14.6.2., paragraph 1 of the standard suggests
strongly that the use of bar in the member function baz
does not denote a dependent name.
|
Correct. bar is an unqualified name, and the parameter supplied is not
type-dependent, so bar is not a dependent name. bar is therefore looked up in
the context of the definition of X, and resolves to the member function
X::bar, as the only bar in scope.
| Quote: | On the other hand, section 14.6.2.2, paragraph 3 could
suggest that bar is an identifier that is declared with
a dependent type (if one considers the type of the implicit
object parameter X<T>& as a participant in bar's type).
|
This use of bar has been resolved to X<T>::bar, so is a type-dependent
expression, yes.
| Quote: | As such, bar seems to be a non-dependent name that is a type
dependent expression...
|
Correct.
| Quote: | The three C++ compilers I have access to all consider bar(0)
as a type-dependent expression, resulting in the use of foo
in the member function baz being a dependent name.
This is the case even if bar is declared to be a static
member function.
Is this behavior correct?
|
Yes.
| Quote: | How do I derive the answer from the standard?
If I change the class template X to
template<typename T> struct X {
int bar(unsigned int) { };
int bar(T) { };
int baz() {
foo(bar(0));
};
};
the above-mentioned compilers will resolve bar in baz
to call the member function int bar(T).
Thus, bar seems to be considered to be a dependent name, thus
violating 14.6.2., paragraph 1.
|
No. bar is still a non-dependent name; however in this case, the overload
resolution cannot be done until the full signature of bar(T) has been
identified at template instantiation time, so it is bound to the declarations
bar(unsigned int) and bar(T).
Anthony
--
Anthony Williams
Software Developer
Just Software Solutions Ltd
http://www.justsoftwaresolutions.co.uk
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Fri Oct 21, 2005 2:49 pm Post subject: Re: Dependent names |
|
|
[email]michael (AT) mehlich (DOT) com[/email] (Michael Mehlich) writes:
| Quote: | Hello,
I'm trying to understand the notion of "dependent name" in C++
as defined by the ISO standard.
However, I could not derive the proper semantics for the following
program:
#include <iostream
int foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { };
int baz() {
foo(bar(0));
};
};
int foo(int) { std::cout << "intn"; }
int main() {
X
x.baz();
};
|
It's ill-formed
At the very least, you need to get rid of the final semicolon.
And then there's the issue of the missing return statements...
| Quote: | Section 14.6.2., paragraph 1 of the standard suggests
strongly that the use of bar in the member function baz
does not denote a dependent name.
|
Correct.
| Quote: | On the other hand, section 14.6.2.2, paragraph 3 could
suggest that bar is an identifier that is declared with
a dependent type (if one considers the type of the implicit
object parameter X<T>& as a participant in bar's type).
|
That seems like unfortunately vague wording.
| Quote: | As such, bar seems to be a non-dependent name that is a type
dependent expression...
The three C++ compilers I have access to all consider bar(0)
as a type-dependent expression
|
I believe you have access to http://www.comeaucomputing.com/tryitout/.
Try compiling the following with that compiler; I hope you will find
it helpful:
#include <iostream>
void foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { return 0; };
int baz() {
return foo(bar(0));
};
};
int foo(int) { std::cout << "intn"; return 0; }
| Quote: | resulting in the use of foo in the member function baz being a
dependent name. This is the case even if bar is declared to be a
static member function.
Is this behavior correct?
|
No.
| Quote: | How do I derive the answer from the standard?
|
AFAICT, the only way is to understand the type of a non-dependent name
that denotes a (member) function to be its return type.
I think this is a wording problem in the standard that should be
fixed.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Fri Oct 21, 2005 2:49 pm Post subject: Re: Dependent names |
|
|
Michael Mehlich wrote:
| Quote: | template<typename T> struct X {
int bar(unsigned int) { };
int baz() {
foo(bar(0));
};
};
|
The key to understanding this is in 9.3.1/2, which is
hard to find because it's not about templates. That
paragraph says
When an id-expression ... is used in the body of a
nonstatic member function of class X ... if name lookup
... resolves the name in the id-expression to a nonstatic
nontype member of class X ..., the id-expression is
transformed into a class member access expression ...
using (*this)...
So the definition of baz transforms into
int baz() { foo((*this).bar(0)); }
becuase bar is found in the way 9.3.1/2 specifies. Now the
argument of foo is seen to be dependent because 'this' is
dependent by 14.6.2.2/2 (its type is X<T>*). So foo itself
becomes a dependent name. Very tricky and counterintuitive.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Sun Oct 23, 2005 5:49 am Post subject: Re: Dependent names |
|
|
Michael Mehlich wrote:
| Quote: | Hello,
I'm trying to understand the notion of "dependent name" in C++
as defined by the ISO standard.
However, I could not derive the proper semantics for the following
program:
#include <iostream
int foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { };
int baz() {
foo(bar(0));
};
};
int foo(int) { std::cout << "intn"; }
int main() {
X
x.baz();
};
Section 14.6.2., paragraph 1 of the standard suggests
strongly that the use of bar in the member function baz
does not denote a dependent name.
|
Indeed.
| Quote: | On the other hand, section 14.6.2.2, paragraph 3 could
suggest that bar is an identifier that is declared with
a dependent type (if one considers the type of the implicit
object parameter X<T>& as a participant in bar's type).
|
No, inside the definition of X<T>, X<T> itself is not considered
template dependent. (This notion has been made considerably
clearer in the current working paper. Specifically, 14.6.4.1 has
been rewritten.)
| Quote: | As such, bar seems to be a non-dependent name that is a type
dependent expression...
|
See above, it's plainly nondependent. But...
| Quote: | The three C++ compilers I have access to all consider bar(0)
as a type-dependent expression, resulting in the use of foo
in the member function baz being a dependent name.
This is the case even if bar is declared to be a static
member function.
Is this behavior correct?
|
Certainly not. Even if you could somehow conclude that
in "foo(bar(0))" the "foo" is subject to a lookup at the
point of instantiation (the so-called "phase-2 lookup),
that lookup is only an "argument-dependent lookup"
(ADL). In this case, the type of bar(0) at the point of
instantiation is "int", which has no associated namespaces
and therefore ADL adds nothing in phase 2. So you'd
still end up calling only a candidate found in phase 1
using ordinary lookup (OL): In this case foo(char) is the
only such candidate.
Most compilers get this completely wrong: They do all
lookups (OL and ADL) for names that appear in function
template definitions at the point of instantiation. (That
because they don't even parse those templates in generic
form -- mostly for historical reasons.) Among the few
that do some lookup in phase 1, most seem to still do
something not quite right with the OL/ADL split.
(But as explained above, the call to foo and bar are both
nondependent, and therefore both OL and ADL must be
done in phase 1 in this example.)
| Quote: | How do I derive the answer from the standard?
|
See above. A current copy of the working paper is
probably needed to pick up all the recent clarifications
in this area.
| Quote: | If I change the class template X to
template<typename T> struct X {
int bar(unsigned int) { };
int bar(T) { };
int baz() {
foo(bar(0));
};
};
the above-mentioned compilers will resolve bar in baz
to call the member function int bar(T).
Thus, bar seems to be considered to be a dependent name, thus
violating 14.6.2., paragraph 1.
However, if bar in baz is not a dependent name, then it must
be bound during template definition, requiring that int bar(T)
is ignored (as dependent on the template parameter), and therefore
bar in baz is bound to int bar(unsigned int)...
|
bar in bar(0) is indeed nondependent, and so subject to the
rules of 14.6.3. However, that doesn't preclude it from finding
both bar(T) and bar(unsigned), so that eventually bar<int>(int)
is selected for the call.
Can you elaborate on why you think bar(T) might need to be
ignored?
Anyway, I hope the above somewhat clarifies things.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
pongba@gmail.com Guest
|
Posted: Tue Oct 25, 2005 2:52 am Post subject: Re: Dependent names |
|
|
but comeau emits an error.
"ComeauTest.c", line 8: error: more than one instance of overloaded
function
"X<T>::bar" matches the argument list, the choices that match
are:
function "X<T>::bar(unsigned int)"
function "X<T>::bar(T)"
The argument types that you used are: (int)
foo(bar(0));
IMO, the real question is, what does the 'bound' in 14.6.3 mean?
Does it mean an overload resolution? If it is, here the resolution
really can't be done because bar(T) is
essentially not a function template so that it's 'T' couldn't be
deduced. But comeau compiler seems not want to kick it out
of the candidate set,but emit an error instead.
Does there exists any statement in the standard that makes this clear?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Tue Oct 25, 2005 10:50 pm Post subject: Re: Dependent names |
|
|
[email]pongba (AT) gmail (DOT) com[/email] wrote:
| Quote: | but comeau emits an error.
"ComeauTest.c", line 8: error: more than one instance of overloaded
function
"X<T>::bar" matches the argument list, the choices that match
are:
function "X<T>::bar(unsigned int)"
function "X<T>::bar(T)"
The argument types that you used are: (int)
foo(bar(0));
|
I believe that's an EDG bug, unfortunately. I've entered a defect
report
for it.
| Quote: | IMO, the real question is, what does the 'bound' in 14.6.3 mean?
|
It means that the set of entities referred to by the name is fully
determined.
| Quote: | Does it mean an overload resolution?
|
No.
| Quote: | If it is, here the resolution
really can't be done because bar(T) is
essentially not a function template so that it's 'T' couldn't be
deduced.
|
That's right.
| Quote: | But comeau compiler seems not want to kick it out
of the candidate set,but emit an error instead.
Does there exists any statement in the standard that makes this clear?
|
There does appear to be a problem with the standard wording in
this case. I've submitted a core issue to address it. One possible
interpretation is what while "bar" is a nondependent name by
14.6.2/1 (so it is bound in phase 1), it is a type-dependent
expression by 14.6.2.2/3 (with a change required to deal with
overload sets). (All references into the current WP.) I don't
particularly like that answer, but it seems viable.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Thu Oct 27, 2005 12:19 am Post subject: Re: Dependent names |
|
|
[email]google (AT) vandevoorde (DOT) com[/email] wrote:
| Quote: | I believe that's an EDG bug, unfortunately. I've entered a defect
report for it.
|
Did you see my comment about 9.3.1/2? Do you disagree that
this is what causes the name to be dependent?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Fri Oct 28, 2005 4:51 pm Post subject: Re: Dependent names |
|
|
Hyman Rosen wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
I believe that's an EDG bug, unfortunately. I've entered a defect
report for it.
Did you see my comment about 9.3.1/2? Do you disagree that
this is what causes the name to be dependent?
|
I did read. Sorry for not responding.
Unfortunately, no, that does no apply because that happens _after_
full binding (when you know that you are dealing with a nonstatic
member function), whereas whether a name is dependent or not
must be determined earlier (hence the rules are mostly syntactic
or at most based on phase-1 lookup only).
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Fri Oct 28, 2005 5:30 pm Post subject: Re: Dependent names |
|
|
[email]google (AT) vandevoorde (DOT) com[/email] wrote:
| Quote: | Hyman Rosen wrote:
Did you see my comment about 9.3.1/2? Do you disagree that
this is what causes the name to be dependent?
Unfortunately, no, that does no apply because that happens _after_
full binding (when you know that you are dealing with a nonstatic
member function), whereas whether a name is dependent or not
must be determined earlier (hence the rules are mostly syntactic
or at most based on phase-1 lookup only).
|
I'm not so sure you're right. Let me quote 9.3.1/2 for reference:
When an id-expression ... is used in the body of a nonstatic
member function of class X ..., if name lookup (3.4.1) resolves
the name in the id-expression to a nonstatic nontype member of
class X or of a base class of X, the id-expression is transformed
into a class member access expression (5.2.5) using (*this) (9.3.2)
as the postfix-expression to the left of the . operator. ...
Similarly during name lookup, when an unqualified-id (5.1) used in
the definition of a member function for class X resolves to a static
member ... of class X ..., the unqualified-id is transformed into a
qualified-id (5.1) in which the nested-name-specifier names the class
of the member function.
Notice that phrase "Similarly during name lookup". That strongly implies
that both transformations, nonstatic and static, take place when the name
is looked up. Now, with 14.6.2/1 saying
In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an identifier, the identifier denotes
a dependent name if and only if any of the expressions in the
expression-list is a type-dependent expression (14.6.2.2).
the expression-list must be examined first, and therefore the transformation
using 'this' will have already happened, causing the function name to become
dependent.
Now, maybe 9.3.1/2 should not be interpreted that way, but why not?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Sun Oct 30, 2005 5:34 pm Post subject: Re: Dependent names |
|
|
Forget that bit about the access violation issues. I misread the
meaning of
"the class of the member function" in that paragraph of 9.3.1.
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Sun Oct 30, 2005 5:34 pm Post subject: Re: Dependent names |
|
|
Hyman Rosen wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
Hyman Rosen wrote:
Did you see my comment about 9.3.1/2? Do you disagree that
this is what causes the name to be dependent?
Unfortunately, no, that does no apply because that happens _after_
full binding (when you know that you are dealing with a nonstatic
member function), whereas whether a name is dependent or not
must be determined earlier (hence the rules are mostly syntactic
or at most based on phase-1 lookup only).
I'm not so sure you're right. Let me quote 9.3.1/2 for reference:
When an id-expression ... is used in the body of a nonstatic
member function of class X ..., if name lookup (3.4.1) resolves
the name in the id-expression to a nonstatic nontype member of
class X or of a base class of X, the id-expression is transformed
into a class member access expression (5.2.5) using (*this) (9.3.2)
as the postfix-expression to the left of the . operator. ...
Similarly during name lookup, when an unqualified-id (5.1) used in
the definition of a member function for class X resolves to a static
member ... of class X ..., the unqualified-id is transformed into a
qualified-id (5.1) in which the nested-name-specifier names the class
of the member function.
|
Note that this means that "f()" is transformed into something like
"(*this).f()" or "C::f()" (but not for example "f(*this)"). I.e.,
after
this transformation, the call is no longer of the form
identifier (expression-list_opt)
So the following would no longer apply:
| Quote: | Notice that phrase "Similarly during name lookup". That strongly implies
that both transformations, nonstatic and static, take place when the name
is looked up. Now, with 14.6.2/1 saying
In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an identifier, the identifier denotes
a dependent name if and only if any of the expressions in the
expression-list is a type-dependent expression (14.6.2.2).
the expression-list must be examined first, and therefore the transformation
using 'this' will have already happened, causing the function name to become
dependent.
|
9.3.1/2 is not a token transformation. I.e., it's not meant to say
that a certain token sequence should be reparsed as another and
then conclusions drawn from that. Instead, it's meant to be a
semantic equivalence transformation to determine the meaning
of a call. For a given call "f()", the transformation may have to be
done (in principle) several times for each member of an overload
set (and it may be different for the different members if some are
static and others are nonstatic). The semantic consequences of
the transformation can then affect overload resolution.
(Now that I think of it, I wonder if 9.3.1/2 might have a defect
wrt. access violations when combined with using declarations?)
The core of much 14.6.2/1 on the other hand is mainly a syntactic
rule: "If you see token sequence with such and such properties,
then do lookup first this way".
I do agree with you that the words "Similarly, during name lookup..."
suggest that the transformation happens so early as to be equivalent
to a token rewrite. Maybe that deserves a core issue. I'll look into
it.
Thanks,
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Mon Oct 31, 2005 2:45 pm Post subject: Re: Dependent names |
|
|
[email]google (AT) vandevoorde (DOT) com[/email] wrote:
| Quote: | Note that this means that "f()" is transformed into something like
"(*this).f()" or "C::f()" (but not for example "f(*this)"). I.e.,
after this transformation, the call is no longer of the form
identifier (expression-list_opt)
So the following would no longer apply:
|
I think you're forgetting the OP's example:
#include <iostream>
int foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { };
int baz() { foo(bar(0)); };
};
int foo(int) { std::cout << "intn"; }
int main() { X
It's the 'bar' in the 'foo(bar(0))' expression which becomes
foo((*this).bar(0))
because name lookup on 'bar' finds a nonstatic member name.
Then this affects whether 'foo' is a dependent name, because
that call is still in the proper form.
Now, I believe it is indisputable that if the code is actually
*written* as 'foo((*this).bar(0))' then 'foo' is a dependent name,
because of 14.6.2.2/2. In that case, it seems to me that it would
be very confusing to treat 'foo(bar(0))' differently, given that
this expression means the same thing as the other one.
I think the way out of this problem is to augment the set of things
in 14.6.2.2/3 which are not type-dependent to include calls to member
functions, whether static or nonstatic and whether they use (*this).f()
this->f(), or plain f(), unless the return type is type-dependent. If
we did this, then in both 'foo(bar(0))' and 'foo((*this).bar(0))' we
would find 'foo' not to be type-dependent, and foo(char) would be
called in all cases, which is the only thing that really makes sense.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
google@vandevoorde.com Guest
|
Posted: Wed Nov 02, 2005 3:51 pm Post subject: Re: Dependent names |
|
|
Hyman Rosen wrote:
| Quote: | google (AT) vandevoorde (DOT) com wrote:
Note that this means that "f()" is transformed into something like
"(*this).f()" or "C::f()" (but not for example "f(*this)"). I.e.,
after this transformation, the call is no longer of the form
identifier (expression-list_opt)
So the following would no longer apply:
I think you're forgetting the OP's example:
#include <iostream
int foo(char) { std::cout << "charn"; }
template
int bar(unsigned int) { };
int baz() { foo(bar(0)); };
};
int foo(int) { std::cout << "intn"; }
int main() { X
It's the 'bar' in the 'foo(bar(0))' expression which becomes
foo((*this).bar(0))
because name lookup on 'bar' finds a nonstatic member name.
Then this affects whether 'foo' is a dependent name, because
that call is still in the proper form.
|
I think you're right that I might have lost track of the actual
question. However, it doesn't really make a difference: In
that example for foo and bar are nondependent in the call
to "foo(bar(0))".
As I mentioned in my earliest post, it doesn't actually matter
for the outcome of the call in this example, what the name
dependence is, because no ADL is involved. The following
variation is more interesting:
struct S {};
int foo(char);
template<typename T> struct X {
S* bar(unsigned int) { return 0; };
void baz() { foo(bar(0)); };
};
int foo(S);
int main() { X<int> x; x.baz(); };
This example would be valid if bar(0) were dependent,
but as things stand now, it is invalid.
| Quote: | Now, I believe it is indisputable that if the code is actually
*written* as 'foo((*this).bar(0))' then 'foo' is a dependent name,
because of 14.6.2.2/2.
|
Agreed.
| Quote: | In that case, it seems to me that it would
be very confusing to treat 'foo(bar(0))' differently, given that
this expression means the same thing as the other one.
|
I think it's confusing either way ;-)
The current rules have the advantage that you don't need to
know whether the called function is a member or not to
decide it's a nondependent name.
| Quote: | I think the way out of this problem is to augment the set of things
in 14.6.2.2/3 which are not type-dependent to include calls to member
functions, whether static or nonstatic and whether they use (*this).f()
this->f(), or plain f(), unless the return type is type-dependent. If
we did this, then in both 'foo(bar(0))' and 'foo((*this).bar(0))' we
would find 'foo' not to be type-dependent, and foo(char) would be
called in all cases, which is the only thing that really makes sense.
|
The wording changes that introduced the notion of "current
instantiation" (14.6.2.1) make a small step in that direction in
the sense that for a proper member m of X<T> both "m" and
"X<T>::m" are considered nondependent inside the definition
of X<T>. I think the changes shied away from involving
expression-based qualification constructs (this-> etc.) because
the spectrum of variations is too dense (this->m, (&(*this))->m,
etc.).
Daveed
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| 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
|
|