A
akomiakov
Is there a technical reason why one can't initialize a cost static non-
integral data member in a class?
integral data member in a class?
Is there a technical reason why one can't initialize a cost static non-
integral data member in a class?
Probably not.
Moreover, it should probably be seen the other way around. The bottom
line here is that in C++ normally non-defining declarations can't
include initializers. An exception was made for integral and enum types
only. And the real question here is whether there's a reason for this
exception. The answer is: yes, there is. The exception was made for
constants of integral and enum types in order to allow these constants
to participate in integral constant expressions. For other types there
is no good reason to allow the initialization.
* Andrey Tarasevich:
Sorry, but that statement is in blatant contradiction of fact.
The fact is, this functionality is requested again and again
and again,
* James Kanze:
I'm sorry but that argument doesn't hold water.
I can't see any example where it wouldn't?
Assuming a practical language rule, of course, where the
current sillyness of having to define the identifier
separately (outside the class definition) if it's "used", is
dropped.
Note in that respect: using templating trick all the required
code is in header file, and within current language rules, so
there's no reason that the compiler can't do that rewrite
automatically, and check for errors, and so requirement of
separate definition if "used" is just silly, completely
redundant.
[snip]By whom? I don't recall having seen any such request (but
there was a long period in which I wasn't that active in
standardization, so I easily could have missed it).
I don't know about requests to the standards committee,
except I know it has been discussed. I think that historically
(discussing the last year or so would be absurd, nothing new
is going to make it into C++0x),
with the understanding that there were at least a few
committee members very much against doing the right thing,
nobody would take the trouble of wasting time by making a
formal proposal. Speculating haphazardly, I conjecture that
any proposal that would make some prominent committee members
feel that they'd been made to look like fools,
[snip]James said:For you. For most of the members of the committee (and for all
of the other experts I know), it does. The general feeling is
that ideally, you shouldn't be able to provide the
initialization in the class definition at all---it's an ugly
hack.
One argument I've heard is differences between the compilation host andAlf said:* James Kanze:
I can't see any example where it wouldn't?
For you. For most of the members of the committee (and for all
of the other experts I know), it does. The general feeling is
that ideally, you shouldn't be able to provide the
initialization in the class definition at all---it's an ugly
hack.
[snip]
Actually, I wonder where that assesment comes from. In my coding style (I do
almost exclusively templated code), all code goes into header files. I
rarely ever split declarations from definitions. Being forced to do that
for static const members creates an imbalance in coding style that makes
the non-hack ugly and the hack natural.
I don't think it is a good idea for the standard to legislate style; and for
templated code, the issue is more or less entirely a matter of style.
James Kanze wrote:.
For you. For most of the members of the committee (and for all
of the other experts I know), it does. The general feeling is
that ideally, you shouldn't be able to provide the
initialization in the class definition at all---it's an ugly
hack.
[snip]
Actually, I wonder where that assesment comes from. In my coding style (I do
almost exclusively templated code), all code goes into header files. I
rarely ever split declarations from definitions. Being forced to do that
for static const members creates an imbalance in coding style that makes
the non-hack ugly and the hack natural.
I don't think it is a good idea for the standard to legislate style; and for
templated code, the issue is more or less entirely a matter of style.
One case would be a cross-compiler.Alf said:* Ian Collins:
It's just a specious red herring argument.
That's true, but I don't think they are classed as compile timeAfter all, there's nothing preventing us from defining these constants
with the current language.
There is a case for consistency.It's just that with current rules it's a load of unnecessary notation
and complication and no guaranteed checking that you've fulfilled the
language's requirements.
Now I see else-thread that purportedly C++0x will fix this.
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"
[snip]
Actually, I wonder where that assesment comes from.
In my coding style (I do almost exclusively templated code),
all code goes into header files. I rarely ever split
declarations from definitions.
Being forced to do that for static const members creates an
imbalance in coding style that makes the non-hack ugly and the
hack natural.
I don't think it is a good idea for the standard to legislate
style; and for templated code, the issue is more or less
entirely a matter of style.
James Kanze wrote:.[snip]For you. For most of the members of the committee (and
for all of the other experts I know), it does. The
general feeling is that ideally, you shouldn't be able to
provide the initialization in the class definition at
all---it's an ugly hack.
Actually, I wonder where that assesment comes from. In my
coding style (I do almost exclusively templated code), all
code goes into header files. I rarely ever split
declarations from definitions. Being forced to do that for
static const members creates an imbalance in coding style
that makes the non-hack ugly and the hack natural.
I don't think it is a good idea for the standard to
legislate style; and for templated code, the issue is more
or less entirely a matter of style.
C++09 will allow the in-definition initialization of any
static class member of a "literal" type - including floating
point types. After all, it probably does not make much sense
to most C++ programmers that a constant floating point
variable may be declared in a header file (outside of a class)
- but may not be declared in a header file (inside of a
class):
// header.h
const float kFloatConstant = 1.0f; // OK
class A
{
public:
static const float kFloatConstant = 2.0f; // Error - but OK in C+
+09
}
* Ian Collins:
It's just a specious red herring argument.
After all, there's nothing preventing us from defining these
constants with the current language.
It's just that with current rules it's a load of unnecessary
notation and complication and no guaranteed checking that
you've fulfilled the language's requirements.
Now I see else-thread that purportedly C++0x will fix this.
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"
A always thought the exception for integer types was to remove
the necessity for the old enum hack compile time constant (for
an array size for instance). This was a pain in pre-standard
compilers, just as it is in C today.
It looks like the exception is about to become the rule!
Interesting point. With current compilers, a declaration is onlyJames said:For the rest, it's still a hack: the declaration in the class
itself is still not a definition, and you still have to provide
a definition elsewhere. (And presumably, compilers will still
complain if you use the variable and don't provide a
declaration---with a possible exception if the use involves an
immediate lvalue to rvalue conversion of an integral type.)
James said:[snip]
Actually, I wonder where that assesment comes from.
Well, I heard it from people very close to Stroustrup; they gave
the impression that it was from him.
The actual point, of course, is that according to the standard,
the declaration of a static data member is *not* a definition.
There are also very good reasons for this, or at least, there
were twenty years ago, when the decision was made. And of
course, you can't provide an initializer in a declaration that
is not a definition.
That's the C++ object model, and allowing the initialiser for
integral types (but only if it is a constant) is a hack with
regards to that.
For the moment, I don't know exactly what the counter-proposal
is, so it's hard to argue against it, or agree with it. If the
proposal is that the declaration in the class should be a
definition (and thus, that you don't need a definition
elsewhere), then I'm radically against it; such a rule would
mean that things like:
static int someArray[] ;
would be illegal (since a definition requires a complete type),
and that you'd always have to provide the initializer in the
class (and most of the time, you really don't want to).
I can understand Alf's desire that all types (and not just
integral types) can have an initializer, and that shouldn't be
too hard to specify nor to implement. With regards to his
desire that you not need the separate definition, however, I'd
want to see the actual proposal. I understand the desire, but I
fear that it would require significant rework of the meaning of
definitions and declarations, which in turn is very likely to
have effects elsewhere.
I'm not sure I understand, and I don't quite see what templates
have to do with it. Whether the definition is in the header
file (or a file included from the header file) or in some
separate source file doesn't really change much.
I'm afraid I don't see where templates change anything.
But
whatever. Until there is a concrete proposal, I don't know what
I'm considering.
James said:For the moment, I don't know exactly what the counter-proposal
is, so it's hard to argue against it, or agree with it. Â If the
proposal is that the declaration in the class should be a
definition (and thus, that you don't need a definition
elsewhere), then I'm radically against it; such a rule would
mean that things like:
  static int someArray[] ;
would be illegal (since a definition requires a complete type),
and that you'd always have to provide the initializer in the
class (and most of the time, you really don't want to).
So let's try to reword [9.4.2/2]:
 The declaration of a static data member in its class definition is not a
 definition and may be of an incomplete type other than cv-qualified void
 unless it specifies an initializer, in which case it is a definition and
 the type shall be complete. If the declaration is not a definition, the
 definition for a static data member shall appear in a namespace scope
 enclosing the member?s class definition. In the definition at namespace
 scope, the name of the static data member shall be qualified by its class
 name using the :: operator. The initializer expression in the definition
 of a static data member is in the scope of its class (3.3.6).
What about that?
Interesting point. With current compilers, a declaration is only
required if the address of a static const member is used. Presumably
the value is a compile time constant, so the declaration is not required
in immediate uses.
With a floating point type, this will not be the case. So which rules
will apply in the new standard? If a declaration is required for all
uses, plenty of existing code will break.
OK, thanks.Greg said:Interesting point. With current compilers, a declaration is only
required if the address of a static const member is used. Presumably
the value is a compile time constant, so the declaration is not required
in immediate uses.
With a floating point type, this will not be the case. So which rules
will apply in the new standard? If a declaration is required for all
uses, plenty of existing code will break.
No, the innitialization of static const floating point class members
will not be treated any differently than the way that in-class
initialization of static const integral class members is handled in
the current Standard. Essentially, no out-of-class definition will be
needed for a const static class member (of a literal type) that has
been initialized within a class declaration. Unless, of course, the
program "uses" that class member.
According to the Draft, a variable is "used" if:
An object or non-overloaded function whose name appears as a
potentially-evaluated expression is "used" unless it is an object that
satisfies the requirements for appearing in a constant expression
(5.19) and the lvalue-to-rvalue conversion (4.1) is immediately
applied.[§3.2/2 N2606]
So has C++, just not for class members.Note that C99 has supported constant floating point expressions for
over eight years now, so in some ways, C++ is simply catching up.
James Kanze wrote:
For the moment, I don't know exactly what the
counter-proposal is, so it's hard to argue against it, or
agree with it. If the proposal is that the declaration in
the class should be a definition (and thus, that you don't
need a definition elsewhere), then I'm radically against it;
such a rule would mean that things like:
static int someArray[] ;
would be illegal (since a definition requires a complete
type), and that you'd always have to provide the initializer
in the class (and most of the time, you really don't want
to).
So let's try to reword [9.4.2/2]:
The declaration of a static data member in its class
definition is not a definition and may be of an incomplete
type other than cv-qualified void unless it specifies an
initializer, in which case it is a definition and the type
shall be complete. If the declaration is not a definition,
the definition for a static data member shall appear in a
namespace scope enclosing the member?s class definition. In
the definition at namespace scope, the name of the static
data member shall be qualified by its class name using the
:: operator. The initializer expression in the definition of
a static data member is in the scope of its class (3.3.6).
What about that?
I think, you misunderstood what I meant by splitting declarations and
definitions. I usually write
template < typename T >
class some_class {
void some_method ( some_type some_arg ) {
// implementation
}
};
instead of
template < typename T >
class some_class {
some_result_type some_method ( some_type some_arg );
};
template < typename T >
some_class<T>::some_result_type
some_class<T>::some_method ( some_class<T>::some_type some_arg ) {
// implementation
}
They don't change the technical side of things. However, as
you can see above, the separation of the definition from the
declaration becomes quite wordy for templates.
Moreover, it has very little return for the effort since
compilers by and large do not support export and the main
technical reasons to hide definitions do not apply. That
influences coding style.
See above.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.