Topic: fully qualified names in parameter lists
Author: "Christopher M. Gurnee" <gurnec_at_mediaone_dot_net@127.0.0.1>
Date: 1998/11/24 Raw View
>> Maurizio Vitale wrote in message
<87hfvyz29m.fsf@naxos.esat.kuleuven.ac.be>...
>> > herald the_herald (writer (mystd::cout)); // NOK
<herald and writer are class types, mystd::cout is a class object>
The first time I read this message, the problem went right past me.
Including the error messages helped me a lot.
Are you ready to be confused :> That line, believe it or not, has TWO
ambiguities, leading to three possible meanings:
1. the_herald is declared as an object of type herald, and it is
direct-initialized with the expression "writer(mystd::cout)"
2. the_herald is the declaration of a function that returns type herald
and has a single parameter of type writer that is named "mystd::cout."
Function declarations (but not definitions!) _are_ allowed at block
scope.
3. the_herald is the declaration of a function that returns type herald
and has a single unnamed parameter of type "pointer to function that
returns writer and takes a single argument of type mystd::cout." Just
in case you have trouble understanding this one, take a look at these
examples:
// a function that returns type "return_t" and has a single parameter
// named "array" of type "pointer to element_t"
return_t func(element_t* array);
// this is the exact same thing because the compiler changes
// parameters of type "array of T" to "pointer to T"
return_t func(element_t array[]);
// again, the same thing, but with an unnamed parameter
return_t func(element_t []);
// a function that returns type "return_t" and has a single parameter
// named "ptr_to_func" of type "pointer to function that returns
// param_return_t and takes a single parameter of type inner_param_t
return_t func(param_return_t (*ptr_to_func)(inner_param_t p) );
// this is the exact same thing because the compiler changes
// parameters of type "function T" to "pointer to function T"
return_t func(param_return_t ptr_to_func(inner_param_t p) );
// again, the same thing, but with unnamed parameters
return_t func(param_return_t (inner_param_t) );
Now go back and look at #3. Does it make (more) sense?
So, which is of the three actually used? Naturally, 3, since it is the
most complicated and difficult to understand :)
Actually, that's not true. The general rule is that when there is an
syntactic ambiguity in a construct, always assume that the construct is
a declaration versus anything else. At the point of disambiguation,
only consider the syntax of the language, and whether or not a name is a
type-name. Let's try to apply that rule to your example.
In order for 3 to work, mystd::cout would have to be a type-name. Since
it is not, we can rule this interpretation out.
That leaves 1 and 2. Since both are equally valid (in terms of syntax
only), 2 is chosen because it is a declaration. After 2 is chosen,
semantic rules are examined. In general, id-expressions (the names of
objects specified in declarations) are allowed to be qualified (have
::'s in them), but this is not allowed in paramater names (this is a
*semantic* rule, not a syntactic one). Therefore the construct is an
ill-formed declaration.
The solution to your problem is a lot easier than figuring out that it
is a problem in the first place:
herald the_herald = writer(mystd::cout);
There's no way that could be considered a declaration.
Now, as far as those error messages are concerned:
Maurizio Vitale wrote in message
<87g1be4tj7.fsf@naxos.esat.kuleuven.ac.be>...
>KAI says:
> "kay-error-2.cc", line 23: error: qualified name is not allowed
> herald the_herald (writer (mystd::cout)); // NOK
This one is correct, but not very helpful
>g++ mantains:
> kay-error-2.cc:23: cannot use `::' in parameter declaration
This is the one that helped me. It's saying that the :: in *parameter
declaration* mystd::cout cannot be used. So it thinks (correctly) that
mystd::cout is the name of a parameter (and not an expression to be
converted to type writer).
I'm not sure how clear I was in my analysis above, so feel free to ask
questions or point out places where I may have made mistakes (which is
pretty likely :)
-Chris Gurnee
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Maurizio Vitale <vitale@esat.kuleuven.ac.be>
Date: 1998/11/20 Raw View
"Alex Martelli" <martelli@cadlab.it> writes:
> Maurizio Vitale wrote in message <87hfvyz29m.fsf@naxos.esat.kuleuven.ac.be>...
> >Is the code below valid when BUG is #defined?
> >If not, why?
> [snip]
> >class herald {
> >public:
> > herald (writer& out);
> [snip]
> > herald the_herald (writer (mystd::cout)); // NOK
>
>
> Not valid, because herald::herald requires a non-const
> reference to an object of class writer, while the temporary
> object of class writer that you are building as a part of
> the invocation of this constructor can only be turned into
> a _const_ reference, NOT a _non-const_ one.
That's definitely a problem with the code I posted, but not the
problem I was asking about. Even changing the constructor fo
herald::herald so that it accept a const writer& doesn't make the
compilers happy and both g++ and KAI C++ (an EDG based compiler)
agrees that in:
herald the_herald (writer (mystd::cout)); // NOK
a fully qualified name is not acceptable as argument to writer
(e.g. the error is very much syntactic, at least that's the way it
comes across from the error messages).
KAI says:
"kay-error-2.cc", line 23: error: qualified name is not allowed
herald the_herald (writer (mystd::cout)); // NOK
g++ mantains:
kay-error-2.cc:23: cannot use `::' in parameter declaration
I just cannot figure out why the construct is not valid in the line
where BUG is defined and valid in the following one.
Maurizio
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Alex Martelli" <martelli@cadlab.it>
Date: 1998/11/19 Raw View
Maurizio Vitale wrote in message <87hfvyz29m.fsf@naxos.esat.kuleuven.ac.be>...
>Is the code below valid when BUG is #defined?
>If not, why?
[snip]
>class herald {
>public:
> herald (writer& out);
[snip]
> herald the_herald (writer (mystd::cout)); // NOK
Not valid, because herald::herald requires a non-const
reference to an object of class writer, while the temporary
object of class writer that you are building as a part of
the invocation of this constructor can only be turned into
a _const_ reference, NOT a _non-const_ one.
Stroustrup, Design And Evolution of the C++ Programming
Language, explains why temporary objects are not
accepted where a non-const reference is required --
basically, to let a compiler diagnose what otherwise
would be very frequent and subtle errors, e.g.:
void f(double& d) {
d += 10;
}
int i = 5;
f(i);
if this code were valid, the user would be forever wondering
why i is not in fact modified by f [f would have received its
reference to a temporary double, obtained by conversion
of the integer i, and discarded at the end of the complete
expression in which it is used].
When an argument is passed by reference without const,
this indicates the function must be able to modify the
actual argument (if this is not needed, then declaring
the argument by reference was a mistake; const
reference should be used!); it is therefore considered
inappropriate for a temporary object, that will immediately
disappear, to be the target of such modifications.
Alex
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Maurizio Vitale <vitale@esat.kuleuven.ac.be>
Date: 1998/11/18 Raw View
Is the code below valid when BUG is #defined?
If not, why?
Thanks,
Maurizio
namespace mystd {
class ostream {};
ostream cout;
}
class writer
{
public:
writer (mystd::ostream& out) {}
};
class herald {
public:
herald (writer& out);
};
int
main (int argc, char** argv)
{
#ifdef BUG
herald the_herald (writer (mystd::cout)); // NOK
#else
writer the_writer (mystd::cout); // OK
herald the_herald (the_writer);
#endif
}
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html ]