Right. It's specious.
Uh, note James, lately I've not had the drive I had earlier to
engage in all sorts of long-winded discussions.
I just make my points and if people don't grok 'em, well I
don't any longer feel any strong compulsion to enlighten them
-- let people be idiots, you can't change them, that's my new
motto!
I go through phases like that myself. It causes a lot less
stress.
But I make exception for you since you're not in
ordinary people (idiot) class, but somewhere at opposite end
of scale. Just, still don't expect me to reply to all.
No worry. Much of what I posted was not really an attempt to
disagree with you, but to put things in historical perspective
for other readers: why the current situation is the way it is.
If we didn't have to deal with history, I'm not sure how we'd
specify the language today. But I'm fairly certain that the
language would be specified in a way to allow initializer values
to be specified in the class, and probably in a way to not
require an additional definition if they were specified. For
better or for worse, however, the current specification is a
result of history, and a history in which C compatibility and
the ability to work with classical C linkers was important.
[...]
I think you mean "compile time constant".
More or less. Perhaps it would be more accurate to say that
there is no place in the standard which would require the
compiler to evaluate that expression.
Right. And irrelevant. Misleading though since we're talking
about (other) constants and it might seem to apply to those.
It doesn't.
Yeah, that one. Plus the one limiting in-class initialization.
No. It's a violation of the one definition rule, which is
undefined behavior. I'm at home now, so I can only verify with
g++, but I'm pretty sure that Sun CC behaves similarly.
I've also just noticed that the current draft also modifies
this. In the standard, a definition is required if the variable
is used, period. In the latest draft I have at hand here, it is
required if the variable is used in a way that doesn't result in
an immediate lvalue-to-rvalue conversion, which corresponds
exactly to the behavior of the compilers I have at hand.
But with the above change, corresponds to the behavior of g++
and Sun CC (and probably most other compilers).
Here's one possible proposal, off the cuff, so not sure if
compiles!
struct A
{
static double const x = 1*2;
};
is to be treated as (i.e. compiler rewrites as) C++98 valid code
template< typename Dummy >
struct __A_x
{
static double const x;
};
template< typename Dummy >
double const __A_x<Dummy>::x = 1*2;
struct A: __A_x<void>
{
};
where __A_x is some generated globally unique name, and except
that if there is any way of generally detecting whether A has
a base class (dunno), then such way shall not detect the
presence of __A_x.
Well, that's hardly the language which would be used in the
standard, but it is a good proof of implementability (which is
also necessary---not that I doubted it, but you know how it is).
I rather liked Kai-Uwe's approach, although it still needs a
little work.
Since the rewritten code is valid C++98 code there's no
adjustment of one-definition-rule: it's still in effect as
before, and still rules.
What happens to code which defines the variable (as currently
required)? Does it suddenly become illegal?
If so, hurray (I haven't noticed that, but then I haven't
scrutinized the draft!) -- and if so, it sort of pulls the
rug under James' argument that
"For most of the members of the committee (and for all of the
other experts I know), [There is no imperative language based
reason to allow [these in-class definition initializations]].
The general feeling is that ideally, you shouldn't be able to
provide the initialization in the class definition at all"
You'll have to explain that one to me. There is no imperative
language based reason.
Yeah. And as mentioned earlier that applies to 'for', 'do' and
'while' as well. Your argument was that in spite of that,
most members of the committee and all other experts you know
had embraced the fallacious argument, so that they would not
be likely to consider anything like reason, but with some
support in C++0x draft, although still keeping separate
definition sillyness, that argument has very little force left
it in -- when they can be moved to go most of the way,
perhaps they can be moved to go the teeny tiny little distance
left also?
I think you misunderstood my claim. Given the current object
model (and the one definition rule, etc.), allowing any
initializer is a hack. C++ didn't allow it even for integers
for the longest time, and I'm aware of some experts who don't
like that exception (for whatever reasons). The "imperative
language based reasons" provided the impetus which made the hack
acceptable. (It's not like for, do or while, because they
aren't felt to be hacks.)
Of course, there is a huge distance left for the Most General
Solution, that of introducing something akin to 'inline' for
/data/.
But since we don't really really need that MGS in
practice, no need to waste time convincing.
Actually, it might be a good idea. It expresses exactly what is
really wanted, and solves the problem with the one definition
rule.
Note that in the current draft, you can declare an inline
function to be a constexpr (with serious limitations as to what
you can do in the function, of course); even class types can be
constant expressions, if their non-copy constructors are
constexpr. So IMHO, there is a (new) very strong argument for
providing some sort of mechanism where you don't have to provide
a definition elsewhere: if
struct S { constexpr static inline int f() { return 43 ; } } ;
is legal, and you don't have to provide a definition for f
elsewhere, why should you not be able to do the same thing for a
data object?
Now if only there were enough time to discuss it more
thoroughly. (I seriously like the "inline" idea. The parallel
with functions appeals to me. I obviously can't speak for
the committee on this, but it also sounds like something simple
enough to have a chance of still slipping in. With a strong
argument on grounds of orthogonality: it works with functions,
why not with data members.)