Topic: Defect Report: throw-expression in a constant expression
Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Sat, 17 Aug 2002 11:32:52 GMT Raw View
Allan W wrote:
....
> 2. Is the constant-expression evaluated? (English-language constrants
> aside, I'll presume that it could be possible to find a value of an
> expression without evaluating it!)
I don't see how. The C++ meaning of 'evaluate' in this context is "to
determine the value of".
(Sorry about the long delay - the original version of this message that
I sent out a week ago was deemed excessively sarcastic. The moderators
just got around to telling me so today.)
---
[ 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 ]
Author: Allan_W@my-dejanews.com (Allan W)
Date: Tue, 20 Aug 2002 18:51:07 GMT Raw View
"James Russell Kuyper Jr." <kuyper@wizard.net> wrote
> Allan W wrote:
> ....
> > 2. Is the constant-expression evaluated? (English-language constrants
> > aside, I'll presume that it could be possible to find a value of an
> > expression without evaluating it!)
>
> I don't see how. The C++ meaning of 'evaluate' in this context is "to
> determine the value of".
I think that you've given the English-language meaning, not the C++ meaning.
It seems clear to me that "evaluate" is a run-time operation. However:
char buffer[1024 * 4 + 1];
The program does not have to multiply 1024 times 4 and then add 1 at
runtime, even ignoring the "as-of" rule. The compiler is able to
simplify this to 4097 at compile-time. Therefore, the value is known
even though the expression has not been evaluated. If there's something
in the standard that says otherwise, I'd appreciate a pointer to it.
In fact, I would say loosely (anywhere EXCEPT the standard, which needs
more precision) that the definition of "constant-expression" is "an
expression where the compiler can know the value without having to
evaluate it at runtime."
> (Sorry about the long delay - the original version of this message that
> I sent out a week ago was deemed excessively sarcastic. The moderators
> just got around to telling me so today.)
Thank you, moderators. I'm sure we don't want this conversation to turn
into an insult-a-thon.
---
[ 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 ]
Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Wed, 21 Aug 2002 22:53:17 GMT Raw View
Allan W wrote:
>
> "James Russell Kuyper Jr." <kuyper@wizard.net> wrote
> > Allan W wrote:
> > ....
> > > 2. Is the constant-expression evaluated? (English-language constrants
> > > aside, I'll presume that it could be possible to find a value of an
> > > expression without evaluating it!)
> >
> > I don't see how. The C++ meaning of 'evaluate' in this context is "to
> > determine the value of".
>
> I think that you've given the English-language meaning, not the C++ meaning.
>
> It seems clear to me that "evaluate" is a run-time operation. However:
>
> char buffer[1024 * 4 + 1];
>
> The program does not have to multiply 1024 times 4 and then add 1 at
> runtime, even ignoring the "as-of" rule. The compiler is able to
> simplify this to 4097 at compile-time. Therefore, the value is known
> even though the expression has not been evaluated. If there's something
No, the value can't be known until the expression has been evaluated. In
this case, the expression was evaluated at compile-time rather than at
run time, but that doesn't change the fact that it was evaluated. The
standard isn't picky about the exact timing of the evaluation of
expressions that don't have side-effects.
---
[ 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 ]
Author: anthony <anthony@anthonyw.cjb.net>
Date: Sat, 10 Aug 2002 11:35:47 GMT Raw View
Allan_W@my-dejanews.com (Allan W) writes:
> Martin v. L=F6wis (loewis@informatik.hu-berlin.de) wrote:
>=20
> > > > #include <stdio.h>
> > > > typedef int X[true?throw 4:5];
> > > >=20
> > > > int main(){
> > > > printf("%d\n", sizeof(X)/sizeof(int));
> > > > }
>=20
> I think that the question can be simplified.
>=20
> 8.3.4/1 says,
> In a declaration T D where D has the form
> D1 [ constant-expression(opt) ]
> and the type of the identifier in the declaration T D1 is
> "derived-declarator-type-list T," then the type of the
> identifier of D is an array type...
> and later
> If the constant-expression (5.19) is present, it shall be an
> integral constant expression and its value shall be greater than
> zero.
>=20
> So now we can ask two questions:
>=20
> 1. Does the expression
> true ? throw 5 : 4
> have a value, and is it greater than zero?
>=20
> 2. Is the constant-expression evaluated? (English-language constrants
> aside, I'll presume that it could be possible to find a value of an
> expression without evaluating it!)
>=20
> If the answer to #1 is "NO", then the program is not well-formed.
>=20
> If the answer to #2 is "YES", then we have to throw an exception.
> Where we throw it *from* is problematic -- it isn't in any
> user-defined code, not even a user-defined constructor. Perhaps
> we just assume that some C++ start-up code throws the error, which
> by definition means that the exception can't be caught. This makes
> the "feature" of throwing from a constant-expression have dubious
> use, but at least it's well-defined.
>=20
> If the answer to #1 is "YES" and the answer to #2 is "NO" then
> the throw-specification is never evaluated, and the compiler is
> free to ignore it.
>=20
> Presumably, most of us would like this construct to be considered
> not-well-formed. Therefore, we're hoping that the answer to question
> #1 is NO. If the standard doesn't say this (or if it is open to
> interpretation), then the standard ought to be fixed. I think that's
> all the OP was trying to say, and I totally agree with him.
I wouldn't go so far as to say that "true?throw 4:5" is "not well-formed"=
,
just that it isn't a constant expression. I am quite happy for such an
expression to exist in the program, knowing that it will always throw an
exception, in which case it is just a non-constant rvalue of type int.
So how about "If an expression contains a subexpression which is a throw
expression, then it is not a constant expression", or similar words in th=
e
appropriate paragraph which describes constant expressions (I don't have =
my
copy of the Standard to hand)
Given that such an expression is not constant, it cannot be used as an ar=
ray
size.
Also, consider "((throw 1),2)" --- this construct would also be banned by=
my
wording, and I think quite rightly. However, I would be interested to see=
what
compilers make of it.
Anthony
---
[ 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 ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: 11 Aug 2002 17:00:26 GMT Raw View
anthony@anthonyw.cjb.net (anthony) wrote (abridged):
> So how about "If an expression contains a subexpression which is a throw
> expression, then it is not a constant expression" [...]
That would mean:
false ? throw 2 : 3
was not a constant expression. Yet it seems like reasonable code (if the
subexpressions are the results of suitable #defines).
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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 ]
Author: rmaddox@isicns.com (Randy Maddox)
Date: Mon, 12 Aug 2002 15:35:54 GMT Raw View
loewis@informatik.hu-berlin.de (Martin v. L wis wrote in message news:<j4ptwtd98q.fsf@aramis.informatik.hu-berlin.de>...
>
> Where precisely says the standard that the exception will always be
> thrown?
>
The statement itself says that the exception will always be thrown:
true ? throw 4 : 5
Since 'true' is always true, the 'throw 4' statement will always be
executed if this expression is evaluated.
Randy.
---
[ 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 ]
Author: loewis@informatik.hu-berlin.de (Martin v. =?iso-8859-1?q?L=F6wis?=)
Date: Mon, 12 Aug 2002 16:43:53 GMT Raw View
brangdon@cix.co.uk (Dave Harris) writes:
> That would mean:
> false ? throw 2 : 3
>
> was not a constant expression. Yet it seems like reasonable code (if the
> subexpressions are the results of suitable #defines).
I think this position is debatable. It would be certainly possible to
ban only constant expressions that evaluate to a
throw-expression. However, I doubt that much users would be upset if
throw-expressions were banned from constant expressions altogether.
Regards,
Martin
---
[ 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 ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Mon, 12 Aug 2002 17:52:46 GMT Raw View
brangdon@cix.co.uk (Dave Harris) wrote in message
news:<memo.20020811134735.18057A@brangdon.madasafish.com>...
> anthony@anthonyw.cjb.net (anthony) wrote (abridged):
> > So how about "If an expression contains a subexpression which is a
> > throw expression, then it is not a constant expression" [...]
> That would mean:
> false ? throw 2 : 3
> was not a constant expression. Yet it seems like reasonable code (if
> the subexpressions are the results of suitable #defines).
Given that the only reasonable use for such an expression would be if
the condition were somehow the result of suitable #define's, there is an
implicit supposition that for some other compiler (or whatever the
define's are conditionned on), you would get true instead of false.
The expression is perfectly reasonable in contexts where the array
dimension need not be a constant, e.g.:
int * i = new int[ true ? throw 2 : 3 ] ;
But I can't see any use as a compile time constant. Either false is
always false, regardless of what is defined, etc., and you can just
write 3, or false may be true in some other environment, and you have
the problem of what the expression means.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Mon, 12 Aug 2002 21:14:17 GMT Raw View
brangdon@cix.co.uk (Dave Harris) writes:
> anthony@anthonyw.cjb.net (anthony) wrote (abridged):
> > So how about "If an expression contains a subexpression which is a throw
> > expression, then it is not a constant expression" [...]
>
> That would mean:
> false ? throw 2 : 3
>
> was not a constant expression.
Yes it would.
> Yet it seems like reasonable code (if the
> subexpressions are the results of suitable #defines).
I think it is simpler to say that it is illegal. Consider
flag1?(flag2?throw 2: 3):(flag3?throw 2:(flag4?throw 2:3))
where flag[1-4] are const expressions of boolean type (e.g. non-type template
parameters). Which combinations of values yield legal expressions, and which
illegal expressions?
Anthony
---
[ 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 ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 12 Aug 2002 21:16:06 GMT Raw View
kanze@gabi-soft.de (James Kanze) wrote (abridged):
> But I can't see any use as a compile time constant. Either false is
> always false, regardless of what is defined, etc., and you can just
> write 3, or false may be true in some other environment, and you have
> the problem of what the expression means.
I had in mind two #defines, that changed in sync. Like:
ConfigValueAvailable ? ConfigValue : 5
This is a constant expression with either:
#define ConfigValue 3
#define ConfigValueAvailable 1
or:
#define ConfigValue (throw "Error")
#define ConfigValueAvailable 0
It seemed reasonable to me. Using the throw expression gives safety
because any attempt to use it when it isn't available will raise an error.
The other macro gives a way to test whether the value is safe to use.
I can see the argument for the simpler rule, though. Especially as:
false ? printf("Now?") : 3;
is not a compile-time constant because printf() isn't one, even though we
know at compile-time that printf() won't be invoked.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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 ]
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Tue, 13 Aug 2002 22:59:02 GMT Raw View
On Mon, 12 Aug 2002 21:16:06 GMT, brangdon@cix.co.uk (Dave Harris)
wrote:
>kanze@gabi-soft.de (James Kanze) wrote (abridged):
>> But I can't see any use as a compile time constant. Either false is
>> always false, regardless of what is defined, etc., and you can just
>> write 3, or false may be true in some other environment, and you have
>> the problem of what the expression means.
>
>I had in mind two #defines, that changed in sync. Like:
>
> ConfigValueAvailable ? ConfigValue : 5
>
>This is a constant expression with either:
>
> #define ConfigValue 3
> #define ConfigValueAvailable 1
>
>or:
> #define ConfigValue (throw "Error")
> #define ConfigValueAvailable 0
>
>It seemed reasonable to me.
Frankly what seems reasonable code to you appears horrible to me. I
hope I'm not the only one to have this opinion. To begin with, if you
want different code depending on the value of ConfigValueAvailable you
already have a way to do it.
#if ConfigValueAvailable
please, do this
#else
please, do this instead
#endif
I would hate to work on code where a macro called ConfigValue may
expand to something that is not a value.
In general, I have yet to understand why I can put a throw in a non
constant conditional expression. Just imagine what I think about the
constant case. As to the current discussion, the standard says that
both
true? throw X : 1 // (1)
and
false? throw X : 1 // (2)
are rvalues of type int. The evaluation of (1) doesn't yield any value
however. In other words the expression has type int, but it's
evaluation yields no value. This kind of joke works (until someone
will find some problem, at least) if you assume that evaluation occurs
at run time, because either you have a value or you leave the code
that would need that value. But if you allow (1) to be a constant
expression you have to introduce new rules in all the cases where the
value of the expression (which now must be known at compile-time)
determines the static meaning of the program. Think about the contexts
listed in 5.19/1 (and also to 6.4.2/5). Just to add another example
(we've already seen array declarations):
template <class T>
class A {
static const int val =
numeric_limits<T>::is_specialized? 256 : throw X();
};
Using a throw in a constant expression, like above, makes no sense to
me. What "throw" is it? It's no more a run-time action. There's
nothing that it throws and no path of execution that will ever reach
it. It's just something that you put there, maybe, to have an operand
with no value.
Genny.
---
[ 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 ]
Author: loewis@informatik.hu-berlin.de (Martin v. =?iso-8859-15?q?L=F6wis?=)
Date: Mon, 5 Aug 2002 21:07:42 GMT Raw View
Gennaro Prota <gennaro_prota@yahoo.com> writes:
> >%CXX-E-BADCONSTOPR, this operator is not allowed in a constant expression
>
>
> Comeau C++ 4.3.0 online, says the same. But the error message is at
> least weird because I see neither the prohibition in 5.19 nor a place
> in the standard that states throw is an operator (note: I'm not saying
> that it shouldn't be)
They probably have a time machine that told them the resolution of
this Defect Report :-)
Seriously, I think the resolution to this defect (if it is accepted as
a DR) seems so obvious, that many compiler vendors have anticipated it
(apparently without even checking what the standard says).
> >It also doesn't like this variation:
> > int i = (true ? throw 4 : 5);
> >.............^
> >%CXX-E-BADINITTYP, a value of type "void" cannot be used to initialize an
> > entity of type "int"
> >
>
> And it is seriously non-conformant here (at least if the message is
> truthful about the type of the conditional-expression).
It seems non-conformant regardless: the compiler refuses to accept a
well-formed program. If you just write
true ? throw 4 : 5;
then it will probably accept it, and still analyse the type of the
expression to be void. This would be fine, under the as-if rule. Only
when you try to use the result you notice the bug.
> Which, from non-conformant, makes it likely broken in this regard.
g++ reports an "Internal Compiler Error", so this compiler is doing
fairly well :-)
Regards,
Martin
---
[ 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 ]
Author: rmaddox@isicns.com (Randy Maddox)
Date: Mon, 5 Aug 2002 21:12:51 GMT Raw View
loewis@informatik.hu-berlin.de (Martin v. L wis wrote in message news:<j4sn1urend.fsf@aramis.informatik.hu-berlin.de>...
> rmaddox@isicns.com (Randy Maddox) writes:
>
> > I do agree that the construct is confusing, and perhaps that alone is
> > sufficient reason to ban it, but its behavior does seem to me to be
> > well defined, at least in terms of whether and how the array is
> > initialized.
>
> But that is not the issue. The question is: What is the size of the
> array?
>
But this is the issue. Either an exception is thrown, in which case
the size of the array is not needed, because the array is not created,
or a valid value for the array size is provided to allow it to be
created. The standard is quite clear on what the size of the array
will be, so that is not the question.
The construct is confusing, and exactly when the exception is thrown
is not completely clear, at least not if the array is declared at file
scope. Those are unanswered questions.
Randy.
---
[ 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 ]
Author: rmaddox@isicns.com (Randy Maddox)
Date: Wed, 14 Aug 2002 10:04:29 CST Raw View
Gennaro Prota <gennaro_prota@yahoo.com> wrote in message news:<glbglusajgmipl75e7k9hruqkgahso1hkq@4ax.com>...
>
> template <class T>
> class A {
> static const int val =
> numeric_limits<T>::is_specialized? 256 : throw X();
> };
>
>
> Using a throw in a constant expression, like above, makes no sense to
> me. What "throw" is it? It's no more a run-time action. There's
> nothing that it throws and no path of execution that will ever reach
> it. It's just something that you put there, maybe, to have an operand
> with no value.
>
>
> Genny.
Well, you might be able to make this a compile-time check with
something like the following:
template <class T>
class A
{
#if numeric_limits<T>::is_specialized
static const int val = 256;
#else
#error numeric_limits not specialized for this type
#endif
};
However, as it stands in your example this will be a run-time
evalutation when the constant val is initialized during the data
segment initialization that occurs prior to entry to main(), and the
exception, if thrown at that point, will likely terminate that
initialization.
Randy.
---
[ 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 ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 15 Aug 2002 23:59:06 GMT Raw View
gennaro_prota@yahoo.com (Gennaro Prota) wrote (abridged):
> To begin with, if you want different code depending on the value
> of ConfigValueAvailable you already have a way to do it.
Using conditional compilation in the middle of an expression is not always
convenient. Sometimes it is better to turn the conditions into #defined
values like ConfigValue which can be used like ordinary variables. This is
especially helpful when the expressions may involve several conditionals,
because it can avoid a combinatorial explosion of permutations of #ifs.
But we don't disagree about the main point. Currently I am of the opinion
that throw should never be a constant expression. These two are just too
similar:
false ? abort() : 3 // Not a constant.
false ? throw 2 : 3 // So neither is this.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ 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 ]
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Fri, 16 Aug 2002 10:24:40 CST Raw View
On Thu, 15 Aug 2002 23:59:06 GMT, brangdon@cix.co.uk (Dave Harris)
wrote:
>gennaro_prota@yahoo.com (Gennaro Prota) wrote (abridged):
>> To begin with, if you want different code depending on the value
>> of ConfigValueAvailable you already have a way to do it.
>
>Using conditional compilation in the middle of an expression is not always
>convenient.
That's not the only alternative. Provide some code where you would use
a macro in that way and I'll show how I would implement the same
thing.
>But we don't disagree about the main point. Currently I am of the opinion
>that throw should never be a constant expression.
It seems that I've convinced you :-)
Genny.
---
[ 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 ]
Author: "Hillel Y. Sims" <usenet@phatbasset.com>
Date: Fri, 2 Aug 2002 16:26:48 GMT Raw View
"Martin v. L=F6wis" <loewis@informatik.hu-berlin.de> wrote in message
news:j4wuralrco.fsf@aramis.informatik.hu-berlin.de...
>
> #include <cstdio>
> struct C{
> int x[true?throw 4:5];
> };
>
> int main()
> {
> int d[5];
> if(sizeof(C) < sizeof(d))
> std::printf("yes\n");
> else
> std::printf("no\n");
> }
>
> Will this print 'yes' or 'no'? Notice that no instance of C is
> created, so this surely shouldn't throw an exception.
>
Compaq C++ 6.5 (EDG version 245) on VMS in strict mode says the following
about that construct:
int x[true?throw 4:5];
................^
%CXX-E-BADCONSTOPR, this operator is not allowed in a constant expression
It also doesn't like this variation:
int i =3D (true ? throw 4 : 5);
.............^
%CXX-E-BADINITTYP, a value of type "void" cannot be used to initialize an
entity of type "int"
But it has no complaint about this:
bool b =3D ...
int j =3D (b ? throw 4 : 5);
hys
--
Hillel Y. Sims
FactSet Research Systems
hsims AT factset.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 ]
Author: rmaddox@isicns.com (Randy Maddox)
Date: Fri, 2 Aug 2002 17:44:01 GMT Raw View
kanze@gabi-soft.de (James Kanze) wrote in message news:<d6651fb6.0208010530.f2eadb8@posting.google.com>...
> rmaddox@isicns.com (Randy Maddox) wrote in message
> news:<8c8b368d.0207310714.5a15e74f@posting.google.com>...
> > loewis@informatik.hu-berlin.de (Martin v. L wis wrote in message
> > news:<j4fzy2a263.fsf@aramis.informatik.hu-berlin.de>...
>
> > > The following translation unit appears to be well-formed.
>
> > > int x[true?throw 4:5];
>
> > > According to 5.19, this appears to be an integral constant
> > > expression: it is a conditional expression, involves only literals,
> > > and no assignment, increment, decrement, function-call, or comma
> > > operators. However, if this is well-formed, the standard gives no
> > > meaning to this declaration, since the array bound (8.3.4/1) cannot
> > > be computed.
>
> > > I believe the defect is that throw expressions should also be banned
> > > from constant expressions.
>
> > Although it threw me for a loop at first, I have to agree that the
> > declaration does appear to be well-formed as per 5.19. It also seems
> > that it ought to work as expected, i.e., either the exception is
> > thrown and x is not initialized, in which case the array bound is not
> > required, or x is initialized to a size of 5. In other words, I do
> > not agree that this is a defect.
>
> The problem is that the decision must occur at compile time. In the
> given expression, of course, the exception will always be thrown. But
> the expression is a compile time constant; how do you throw an exception
> at compile time?
>
> --
> James Kanze mailto:jkanze@caicheuvreux.com
> Conseils en informatique orient e objet/
> Beratung in objektorientierter Datenverarbeitung
>
Of course our code cannot throw an exception at compile time, but
arrays are initialized at run time, when we certainly can do so.
Conceptually this is similar to the case of a file-scope static object
with a constructor. That constructor is invoked at run time, prior to
the start of main, and may well throw an exception at that time.
I do agree that the construct is confusing, and perhaps that alone is
sufficient reason to ban it, but its behavior does seem to me to be
well defined, at least in terms of whether and how the array is
initialized.
Of course, there is the related issue of how do you catch an exception
that occurs prior to entry to main. Will a function try block around
main catch such an exception? And what would you do with it if you
caught it? Seems to me that things could get pretty hairy if a user
initialization threw an exception prior to the start of main, perhaps
even before some parts of the stdlib, like std::cout say, were
initialized.
However, banning this particular construct because it might cause
unusual behavior in the gray area prior to the start of main could
logically be followed by a ban on all exceptions prior to entry to
main. That might very well be a good thing, but how would it affect
the rules governing construction of static objects?
This is a really interesting question and it's not at all clear to me
where we go with answers to it.
Randy.
---
[ 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 ]
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Sat, 3 Aug 2002 19:05:09 GMT Raw View
On Fri, 2 Aug 2002 16:26:48 GMT, "Hillel Y. Sims"
<usenet@phatbasset.com> wrote:
>Compaq C++ 6.5 (EDG version 245) on VMS in strict mode says the following
>about that construct:
> int x[true?throw 4:5];
>................^
>%CXX-E-BADCONSTOPR, this operator is not allowed in a constant expression
Comeau C++ 4.3.0 online, says the same. But the error message is at
least weird because I see neither the prohibition in 5.19 nor a place
in the standard that states throw is an operator (note: I'm not saying
that it shouldn't be)
>
>It also doesn't like this variation:
> int i = (true ? throw 4 : 5);
>.............^
>%CXX-E-BADINITTYP, a value of type "void" cannot be used to initialize an
> entity of type "int"
>
And it is seriously non-conformant here (at least if the message is
truthful about the type of the conditional-expression). 5.16/2 says
that
true ? throw 4 : 5
is an rvalue of type int.
>But it has no complaint about this:
> bool b = ...
> int j = (b ? throw 4 : 5);
Which, from non-conformant, makes it likely broken in this regard.
Anyhow what we are discussing here is not the type of the
conditional-expression but whether it can be considered constant or
not.
Genny.
---
[ 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 ]
Author: loewis@informatik.hu-berlin.de (Martin v. =?iso-8859-15?q?L=F6wis?=)
Date: Mon, 5 Aug 2002 02:23:17 GMT Raw View
rmaddox@isicns.com (Randy Maddox) writes:
> I do agree that the construct is confusing, and perhaps that alone is
> sufficient reason to ban it, but its behavior does seem to me to be
> well defined, at least in terms of whether and how the array is
> initialized.
But that is not the issue. The question is: What is the size of the
array?
> Of course, there is the related issue of how do you catch an exception
> that occurs prior to entry to main. Will a function try block around
> main catch such an exception? And what would you do with it if you
> caught it?
That question is unrelated to the question of the array size: An
exception can always occur during initialization of a non-local
object.
3.6.2/4 says that uncaught exceptions here will result in a call to
terminate.
3.6.2/3 says that it is implementation-defined whether those
initializations occur before the first statement of main:
# It is implementation-defined whether or not the dynamic
# initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace
# scope is done before the first statement of main. If the
# initialization is deferred to some point in time after the first
# statement of main, it shall occur before the first use of any
# function or object defined in the same translation unit as the
# object to be initialized.
> However, banning this particular construct because it might cause
> unusual behavior in the gray area prior to the start of main could
> logically be followed by a ban on all exceptions prior to entry to
> main.
That area is not gray at all - the standard is very explicit about all
aspects of it.
Regards,
Martin
---
[ 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 ]
Author: rmaddox@isicns.com (Randy Maddox)
Date: Wed, 31 Jul 2002 17:56:24 GMT Raw View
loewis@informatik.hu-berlin.de (Martin v. L wis wrote in message news:<j4fzy2a263.fsf@aramis.informatik.hu-berlin.de>...
> [ moderator's note: Forwarded to C++ Committee. -sdc ]
>
> The following translation unit appears to be well-formed.
>
> int x[true?throw 4:5];
>
> According to 5.19, this appears to be an integral constant expression:
> it is a conditional expression, involves only literals, and no
> assignment, increment, decrement, function-call, or comma operators.
> However, if this is well-formed, the standard gives no meaning to this
> declaration, since the array bound (8.3.4/1) cannot be computed.
>
> I believe the defect is that throw expressions should also be banned
> from constant expressions.
>
> Regards,
> Martin
>
>
Although it threw me for a loop at first, I have to agree that the
declaration does appear to be well-formed as per 5.19. It also seems
that it ought to work as expected, i.e., either the exception is
thrown and x is not initialized, in which case the array bound is not
required, or x is initialized to a size of 5. In other words, I do
not agree that this is a defect.
However, in spite of that, the MSVC++ compiler version 6.0 chokes on
this construct, complaining that it expected a constant expression and
that the size of x is unknown. This appears to be a deviation from
the standard.
Thanks for the interesting observation.
Randy.
---
[ 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 ]
Author: loewis@informatik.hu-berlin.de (Martin v. =?iso-8859-15?q?L=F6wis?=)
Date: Thu, 1 Aug 2002 21:50:57 GMT Raw View
rmaddox@isicns.com (Randy Maddox) writes:
> > int x[true?throw 4:5];
> Although it threw me for a loop at first, I have to agree that the
> declaration does appear to be well-formed as per 5.19. It also seems
> that it ought to work as expected, i.e., either the exception is
> thrown and x is not initialized, in which case the array bound is not
> required, or x is initialized to a size of 5. In other words, I do
> not agree that this is a defect.
Notice that the evaluation of this expression must be a compile-time
evaluation. In particular, you can ask
int i = sizeof(x);
which must be a compile-time evaluation. Or, to take another example:
#include <cstdio>
struct C{
int x[true?throw 4:5];
};
int main()
{
int d[5];
if(sizeof(C) < sizeof(d))
std::printf("yes\n");
else
std::printf("no\n");
}
Will this print 'yes' or 'no'? Notice that no instance of C is
created, so this surely shouldn't throw an exception.
Regards,
Martin
---
[ 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 ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 1 Aug 2002 21:51:07 GMT Raw View
rmaddox@isicns.com (Randy Maddox) wrote in message
news:<8c8b368d.0207310714.5a15e74f@posting.google.com>...
> loewis@informatik.hu-berlin.de (Martin v. L wis wrote in message
> news:<j4fzy2a263.fsf@aramis.informatik.hu-berlin.de>...
> > The following translation unit appears to be well-formed.
> > int x[true?throw 4:5];
> > According to 5.19, this appears to be an integral constant
> > expression: it is a conditional expression, involves only literals,
> > and no assignment, increment, decrement, function-call, or comma
> > operators. However, if this is well-formed, the standard gives no
> > meaning to this declaration, since the array bound (8.3.4/1) cannot
> > be computed.
> > I believe the defect is that throw expressions should also be banned
> > from constant expressions.
> Although it threw me for a loop at first, I have to agree that the
> declaration does appear to be well-formed as per 5.19. It also seems
> that it ought to work as expected, i.e., either the exception is
> thrown and x is not initialized, in which case the array bound is not
> required, or x is initialized to a size of 5. In other words, I do
> not agree that this is a defect.
The problem is that the decision must occur at compile time. In the
given expression, of course, the exception will always be thrown. But
the expression is a compile time constant; how do you throw an exception
at compile time?
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ 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 ]
Author: loewis@informatik.hu-berlin.de (Martin v. =?iso-8859-15?q?L=F6wis?=)
Date: 29 Jul 2002 17:18:57 GMT Raw View
[ moderator's note: Forwarded to C++ Committee. -sdc ]
The following translation unit appears to be well-formed.
int x[true?throw 4:5];
According to 5.19, this appears to be an integral constant expression:
it is a conditional expression, involves only literals, and no
assignment, increment, decrement, function-call, or comma operators.
However, if this is well-formed, the standard gives no meaning to this
declaration, since the array bound (8.3.4/1) cannot be computed.
I believe the defect is that throw expressions should also be banned
from constant expressions.
Regards,
Martin
[ 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 ]