Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
C++
struct AsVarVal
{
    bool isVar;
    byte varVal;  // 0 to 255

    const static AsVarVal Default = {false, 0};

    AsVarVal()
    {
        *this = Default;
    }
};

like enums i expect other const static data members be initializable inside struct definitions.
then, which one is preferred? const static or static const?
thx
Posted
Comments
Sergey Alexandrovich Kryukov 11-Mar-12 14:39pm    
Is it C++ or C++/CLI?
--SA
ilostmyid2 11-Mar-12 15:17pm    
native C++

This is so wrong in so many way, it would be code-reviewed to oblivion where I work.

Straight code will not compile.

Usually, I write:

static const <t> var;</t>


anyway,
I don't think you can initialize struct/classes like that (on VS11 beta), it will give error C2552:

"Default" non-aggregate cannot be initialized with initializer list 'asVarBal' Types user defined constructors are not aggregate.

I'm not even certain why you re-assigned this in the constructor from a static variable ? are you trying to create a singleton ?

but I'm open to explanation...
Max.
 
Share this answer
 
Comments
ilostmyid2 11-Mar-12 11:28am    
thank u 4 replying
no, it's not going to implement a singleton. in singleton the instance is shared, while here an instance is used for initializing new instances. indeed instead of initializing data members separately in constructor, i would like to initialize new instances by the static instance.
everything is ok if i don't initialize the static instance inside the struct definition. "why"? this is what i can't understand. what's wrong if i initialize the static instance inside the struct definition while it's const when enums may be initialized by the same way. i think this is a lack of C++ or VC++ instead of error in my code. don't u think so? my code is logically true. if not, tell me why it's not.
thx
[no name] 12-Mar-12 10:28am    
You persist with a why - well thats the standard. Here it is from "The C++ Programming Language Third Edition":

10.4.6.2 Member Constants

It is also possible to initialize a static integral constant member by adding a constant-expression initializer to its member declaration. For example:
class Curious {
static const int c1 = 7; // ok, but remember definition
static int c2 = 11; // error: not const
const int c3 = 13; // error: not static
static const int c4 = f(17); // error: in-class initializer not constant
static const float c5 = 7.0; // error: in-class not integral
// ...
};

However, an initialized member must still be (uniquely) defined somewhere, and the initializer may not be repeated:
const int Curious::c1; // necessary, but don't repeat initializer here

I consider this a misfeature. When you need a symbolic constant within a class declaration, use an enumerator (4.8, 14.4.6, 15.3). For example:
class X {
enum { c1 = 7, c2 = 11, c3 = 13, c4 = 17 };
// ...
};

In that way, no member definition is needed elsewhere, and you are not tempted to declare variables, floating-point numbers, etc.
1>c:\visual studio\cpptest\cpptest.cpp(69): error C2059: syntax error : '{'
1>c:\visual studio\cpptest\cpptest.cpp(69): error C2334: unexpected token(s) preceding '{'; skipping apparent function body
1>c:\visual studio\cpptest\cpptest.cpp(73): error C2065: 'Default' : undeclared identifier
=

This is what the compiler threw up when I tried it; it's obviously not valid to try and create a constant of your structure within its definition. And remember this is not the same as an enum.
 
Share this answer
 
Comments
ilostmyid2 11-Mar-12 13:50pm    
yeah, i know that the compiler generates errors for it. but my question is that why semantically it must not be true?
Richard MacCutchan 12-Mar-12 4:18am    
Because those are the rules of the language.
ilostmyid2 12-Mar-12 4:43am    
the rules are put off based on the semantic limitations...
never mind, i had no choice to change my code :(
There are a numbe of things not conforming to the C++ specifications, here:

1) The initialization of a variable of non integral type must be at file level
2) initializing a struct with a brace initilializer list requires the struct to be a POD (POD = Plain Old Data)

To accommodate 1) you must move the initialization outside of the class declaration and to accommodate 2) you must have no constructors.

In this way it works
C++
struct AsVarVal
{
    bool isVar;
    unsigned char varVal;  // 0 to 255

    const static AsVarVal Default;
};

const AsVarVal AsVarVal::Default = {false, 0};


If you want to have constructors, you may have a different approach, like this


C++
struct AsVarVal
{
    bool isVar;
    unsigned char varVal;  // 0 to 255

    AsVarVal() :isVar(false), varVal(0)
    {}

    AsVarVal(bool isVar_, unsigned char varVal_)
        :isVar(isVar_), varVal(varVal_)
    {}
};


[Edit in answer to the comment]

About 1) I meant "conformant to the language specification".
Something none of us wrote. They simply "are".

About 2) Yes, you got it right. About the "why", this is exactly the same rule that says that declarations can be repeated (since they don't instantiate anything, just define symbols for the compiler) but definition cannot.
Why this rule exist, and why C++ use headers as "paste in" (not as "symbols catalogs", like other languages do) ... that's how C++ specification are. The "why" is that C++ must be backward compatible with C that is -in turn- an "high level assembler". And that's how C works.

Note that what you call "class definition" (in 4) ) is in fact a "declaration": it doesn't instantiate any object, it just tells how the class is structured, but doesn't allocate any space for it. It just says how much of it is required.
But an initialized static variable is a definition, since it requires some space to be reserved for it.

Integral constants -in this context- are an exception to that general rule that can be tolerated just because integrals are evaluated by the compiler itself (in fact an integral constant is not allocated as an object: it is just a number that will replace the constant symbol in every place it is used). The reason of this exception resides in the fact that operation taking an integer as a parameter can be translated directly in a single machine code instruction on the most of the processors. Other type of constants don't fit a single instruction and require a reference or a data move (and hence "space" in the data memory)

About 3) The term "Plain Old Data" (abbreviated as POD) is what the C++ language specs calls "a struct that conforms to the C subset specs C++ is based on". Essentially C struct (with no constructor, destructor, access specifiers, virtual methods etc.)

About 4) I can understand your feeling (C++ is not a simple language...), but -technically speacking- my solutions aren't workarounds: they are nothign more that what the language specifications require.

By looking at your code, it seems you are using C++ as it is Java or C#.
C++ is a completely different language with a completely different philosophy. That leads to a completely different coding style and patterns implementation.
 
Share this answer
 
v2
Comments
ilostmyid2 11-Mar-12 23:49pm    
hithank for replying
1) i couldn't find what u meant by conformant.
2) i couldn't find what u meant by file level. do u mean a static const data member must be initialized in the source and can't be initialized in the header file at class/struct definition? if u mean this, it's the source of my question, not the answer. why it must not be possible to initialize a non-integral static const data member of a class in the class definition? what's the logic beyond it?
3) i couldn't find what u meant by plain old data.
4) my question is exactly this. why i must move the initialization outside of the class definition?! now i've no constructor.
i think the solution is a workaround for the code to work. thank u, but i wanted the answer to the "why" i asked.
Emilio Garavaglia 12-Mar-12 18:17pm    
Answer updated.
ilostmyid2 13-Mar-12 0:14am    
i thought like u b4 about definition of a class and its difference with a class declaration. but after reading some pages in MSDN i found that a class declaration is like:
class CSomeClass;
and its definition is like:
class CSomeClass
{
...
};
the definition of class member functions differs from the definition of the class itself. what we see in a class definition is its member functions declarations. the definitions of the class member functions is usually put in source files. a function declaration may be called its prototype. defining an instance to a class differs from defining the class itself.
still about 2, maybe a good justification, but not fitting into one instruction may not be a problem. assigning a block of const data in compile time whenever needed may not lead to allocating a block of data in run-time. i think "they just didn't want to implement it", not it's semantically confront logic. this causes me to allocate a block of data in run-time which is const and don't need to be modified!
about 3 i think u mean what VS calls aggregate, right?
indeed it's about 3 months i've begin coding in C# and found it so amazing. it's more object oriented. there's no basic type. everything is derived from object. many things that is not possible in C++ is possible there. u don't have to worry about many things, eg. buffer overrun, etc. maybe this is why my expectations r upgraded! :D
thank u. treating a static const int as a const involving in machine code instructions maybe a good justification, although i still think that there might still be good ways to implement non-integral types. there're floating point registers for example in many CPU's. i think they've stopped upgrading C++ more than this. maybe a C+=2! language must be invented! :D
thank u anyway
Emilio Garavaglia 13-Mar-12 3:58am    
The reliable source about C++ specification is the specification itself, not MSDN.

As per the spcs:

class FORWARD DECLARATION is
class A;
(just a symbol)

class DECLARATION is
class A { ... };
(just a bunch of symbols and a way to compute space)

method DECLARATION is
rettype name(params ...);
(again just symbols)

method DEFINITION is
rettype name(params ...) { ... }
(imply machine code to be produced)

varaible DEFINITION is
type name = type(params ...); (or other syntactic shortcuts)
(imply the reservation of memory space)

There is no concept of "class definition" since a non instantiated class is ... nothing.

You can mix method definitions into class declarations, like
class A { void method() {} };
because that definition, being into a class decl, is implicitly considered as inline and hence CAN BE REPEATED, like inline function are (and stay in header files).

But C++ designed din't define an equivalent "inline variable definition" hence static variables definitions - like all variables or non integral constants - cannot be repeated, hence canto stay into a declaration.

About your comparison of C# and C++, you can have all the personal opinion you like, but what you did is a technical nonsense: if C++ must be like C# it will be c# itself and if C# must be like C++ will be C++ itself.

C++ and C# are different languages that target different programming domains.
C++ is closer to the metal than C# actually is: "everyting derived from object" is considered bad practice from modern C++ programmers, since will lead to unnecessary overhead for certain kind of situation a SYSTEM programmer have to deal with and a USER programmer (I mean a programmer writing useer-targetted programs) don't have to.

The correct answer is choose the appropriate language for the problem you have to solve and respect the design guides that language carries on. Don't try to make one to work as the other: it just mean you are using the wrong one. Just use the other.

The main difference between C# and C++ is that in C# objects are "referenced", while in C++ objects are "values". And references have to be explicitly managed.

What I proposed is not a "workaround to make things to work". Is what C++ requires an object to be designed. That's a completely different story than what C# requires.
ilostmyid2 13-Mar-12 5:06am    
i would prefer to use C if i would like to write a program to be close to metal. in C++ some things are not object, while the language intended to be object oriented.
about the first section, thank u, i will keep them in mind and if i will read some documents containing "class definition" i hope i won't forget to inform u, although u said that the Microsoft documents must not be treated as criterion. would u give me the source document of what is called a class declaration, pls?
i still believe that a const aggregate is implementable by the compiler and there's no need for a static instance. i also believe that there's no proof for a non-static const integral value not to be initializable inside a class declaration/definition. a const data member would better not to be treated as a data member! it's const anyway. so there's no need to allocate a space for it to consume in run-time!
i know that i've no choice. i'm not the designer of C++ and nothing changes by my opinions, but i think it's a good idea to think and discuss about what would be better to be noticed when designing. maybe the designers or MS ppl come here and see our discussions and upgrade their newer versions based on what they think to be more logic between our words, even though it becomes more MS specific and gets more non-standard. then, maybe the standards get updated based on what we think to be more logic.
i also thank u for "forward declaration" phrase. i'd not heard it b4.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900