Archived

This topic is now archived and is closed to further replies.

How do I define a constant expression with in a class?

This topic is 5504 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My program was written using GCC and now I''m trying to port it to MSVC++ 6.0 (which is proving to be a big headache). I''ve managed to fix most of the errors, but there is one big problem that VC++ bitches about that GCC doesn''t care about:
  
class MyClass {

   static const int MY_CONST = 1234;

};
  
I get the errors :
error C2258: illegal pure syntax, must be ''= 0''
error C2252: ''MY_CONST'' : pure specifier can only be specified for functions
 
This can be fixed by putting the constant in the source file instead of the header file. But there is one case where I can''t move it:
  
class OtherClass{

   static const int MY_CONST; // this is assigned a value in the source file instead of here

 
   int arr[OtherClass::MY_CONST];

};
  
Now, if I try to compile it,
error C2057: expected constant expression
warning C4200: nonstandard extension used : zero-sized array in struct/union
 
Is there some way to fix this knot? Thanks for your help.

Share this post


Link to post
Share on other sites
First, static and const are redundant, and I believe static can only be used for functions, though I might be wrong. I would recommend whacking the static part of your code and trying again. That should fix the problem. Otherwise, use an enumeration (enum).

Then again, I''m one of the most hated people in all of computer programming...a Borland user. Ahh! Run for your lives!

Share this post


Link to post
Share on other sites
Whats''s wrong with Borland?

At least Borland lets you do:

for (int i=sometging; blah; blah)
for (int i=sometging; blah; blah)
for (int i=sometging; blah; blah)

But MS complains about the earlie declaration of i. Bah.

Share this post


Link to post
Share on other sites
quote:
Original post by Racso
First, static and const are redundant, and I believe static can only be used for functions, though I might be wrong.


Actually, you''re wrong on both accounts. Static and const are two completely different things. He wants a single constant used by all instances of the class. If he did just static, then the value would be editable, if he did just const, then there would be an instance of it in every single object! He doesn''t want either of those he wants them both at the same time. Thinking static is only applicable to functions makes me think that you probably don''t understand what static means.

Anyways, the enum version is the best -- while it doesn''t make a constant in memory, it gives the same effect as what you want (unless at some point you want to use the value''s memory address because with an enum it won''t have one). Don''t put extra stuff in memory when you can avoid it. Enumerations are fine in this case.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
In a .h file

class foo
{
public:
static const int CONST;
}

in a .cpp

const int foo::CONST = 1234;

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
In a .h file

class foo
{
public:
static const int CONST;
}

in a .cpp

const int foo::CONST = 1234;


He knows he can do that, but his point is that he has another variable in the class that is dependent on the value. In this case, what you mentioned will not solve his problem. Using enum is what he should be doing.

Share this post


Link to post
Share on other sites
quote:
Original post by Racso
Then again, I''m one of the most hated people in all of computer programming...a Borland user. Ahh! Run for your lives!




Fear not - for you are not the only one. Besides, one should take great pride in the ability to resist Microsoft''s wicked contraptions most of the people seem to be so fond of. Borland rules - too bad they''re not too much of a hurdle for MS to jump over, thought - takes all the fun out of it .

PS - I''m not flaming MS, this is just a personal opinion - me against VC (I am a Windows user, so I can''t really flush that - garn...), if you like...

Crispy

Share this post


Link to post
Share on other sites
quote:
Original post by ChaosEngine
That''s realyl a bit of a language flaw isn''t it?


Nope, not at all. It actually makes perfect sense and is not a flaw. The reason it doesn''t work is because the compiler has to know how much data to be allocated for the array. It can''t do this if the constant is defined in another file because the value can be anything.

If he really wanted the same value for the constant he can still make it and set both that value and the length of the array to the same constant.

Share this post


Link to post
Share on other sites
quote:
Original post by __tunjin__
class foo
{
enum { bar = 1; }

// ...
};

This works well. Thanks for the suggestion.

quote:
Original post by Lektrix
If you want to use a static member it should be:

const static int MY_CONST = 1234;

not:

static const int My_CONST = 1234;

It should work fine then.


That is weird Is there such a thing as a static const? What is the difference? The const keyword is one that I find to be somewhat elusive because there are so many usages (like why would someone put const at the end of a function or method?).


quote:
Original post by Matt Calabrese
If he really wanted the same value for the constant he can still make it and set both that value and the length of the array to the same constant.


Isn't that the purpose of using constants is to get away from magic numbers all over the place?


quote:
Original post by Matt Calabrese
Anyways, the enum version is the best -- while it doesn't make a constant in memory, it gives the same effect as what you want (unless at some point you want to use the value's memory address because with an enum it won't have one). Don't put extra stuff in memory when you can avoid it. Enumerations are fine in this case.


So are enums similar to a #define statement?

For example:

#define MY_CONST 12
enum { MY_CONST = 12 };

Both lines produce the same results?

Thanks for the information.




[edited by - spiffgq on November 18, 2002 9:52:54 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Lektrix
If you want to use a static member it should be:

const static int MY_CONST = 1234;

not:

static const int My_CONST = 1234;

It should work fine then.


There is no difference, it''s just a matter of choice. Both will do the exact same thing.

quote:
Isn''t that the purpose of using constants is to get away from magic numbers all over the place?


That''s also the purpose of enum and #define. The reason you''d use them over constants is because enum and #define don''t take up any space in memory. You can still use them as magic numbers, but theres no point in setting aside a special place in memory for them.

IE. enum Foo { Bar = 1 };

Doesn''t create a constant in memory, but rather, when you use the word "Bar," the compiler replaces it with the value 1 (plus you get added type-safety). However, if you did

const int Bar = 1;

Then, when you''d "Bar," the value would be checked at runtime. So it''s actually [very] slightly slower and takes up extra space in memory that''s not necissary.

Basically, use const for "magic data" when you are dealing objects, not integers, etc. Or when you actually need to pass the memory location of the magic number.

quote:
So are enums similar to a #define statement?


Very similar, but, as I said, there''s also that bonus of type-safety. When you do

enum Foo { Bar = 1 };

You are not only saying that Bar equals 1, but you are also making it of the new datatype "Foo." If you are using it simply as a magic number, then #define might make more sense (for instance if it represents gravity in a game, etc.), however, if it represents something like an enumerated value that represents a subclass, then you are better off using enum. It''s very subjective, but that''s generally the idea.

Reflecting on what we said earlier it really is probably better to use #define instead of enum in this case just because it really is just a "magic number" that''s not of it''s own datatype. Once again, though, it''s really just a choice that you can make and whether you use #define or enum doesn''t really make a difference.

Share this post


Link to post
Share on other sites
In short... #define is ''used'' as a text replacement thingy. Try the menu [Edit|Find and Replace] and you''ll know what I mean. enum is a better choice.
quote:

...
IE. enum Foo { Bar = 1 };

Doesn''t create a constant in memory...


Are you *very* sure about this? How does the program ''knows'' or ''remember'' this value in the compiled binary code? Think about it....

hmm... I remember there are few posts about these... anyone could point it out where?

Share this post


Link to post
Share on other sites
quote:

Are you *very* sure about this? How does the program ''knows'' or ''remember'' this value in the compiled binary code? Think about it....




Enum does not create an variable in memory. When the source is compiled into binary, the enum is worked out at compiled time and itis replaced by the value.
In other works it ends up acts as if you hard coded the magic numbers in there.

And enum are much more useful in generative programming where you want the compiler to evaluate a expression at compile time.

-----------------------------
Gamedev for learning.
libGDN for putting it all together.

Share this post


Link to post
Share on other sites
quote:
Original post by DerekSaw
How does the program ''knows'' or ''remember'' this value in the compiled binary code?
The same way as if you''d used #defines - it replaces each use of the constant with the corresponding magic number.

Share this post


Link to post
Share on other sites
quote:
Original post by spiffgq
That is weird Is there such a thing as a static const? What is the difference? The const keyword is one that I find to be somewhat elusive because there are so many usages (like why would someone put const at the end of a function or method?).



static and const are completely unrelated. const means that something isn't going to change. Putting const at the end of a function means that the function isn't going to alter the objects data.

This won't work:

    
class foo
{
public:
void bar(void) {}
foo() {}
};

int main(void)
{
const foo bar;
bar.bar(); // you can't do this because the function might alter the object


return 0;
}


This will:


  
class foo
{
public:
void bar(void) const {}
foo() {}
};

int main(void)
{
const foo bar;
bar.bar(); // It works now. Yay!!!


return 0;
}


[edited by - smart_idiot on November 18, 2002 11:11:28 PM]

Share this post


Link to post
Share on other sites
Just an interesting note, you can also declare variables to be mutable, in which you can change the variable even if whatever has it is constant.


  
class foo
{
public:
mutable int bar;
foo(): bar(0) {}
};

int main(void)
{
const foo bar;
bar.bar = 4;

return 0;
}

Share this post


Link to post
Share on other sites
quote:
Original post by Kurioes
Whats''s wrong with Borland?

At least Borland lets you do:

for (int i=sometging; blah; blah)
for (int i=sometging; blah; blah)
for (int i=sometging; blah; blah)

But MS complains about the earlie declaration of i. Bah.


You can do that with g++ but I don''t really recommend it because can get confusing.

Share this post


Link to post
Share on other sites
Yes, variables use memory... so do constants.
and yes again, constants are solved at compile time.
But, where does those ''magic numbers'' stored? Sure they need some reference... and the reference I''m very sure is in the .EXE... and if it''s in the .EXE, then it will used up portion of memory as well. Let''s say:

  
#define SOME_DISTINCT_VALUE 0x12345678
int main()
{
cout << SOME_DISTINCT_VALUE << endl;
return 0;
}

Try search for the value 0x12345678 (maybe it is byte sequence: 78 56 34 12) in your .exe file using some hex editor. It does use spaces in your .exe file. If it does use spaces in the .exe file, I''m sure it will use memory as well. If this one is not enough, you could try replacing it with string (for easy searching ). Dare to try it?

p/s: And if you #define it, but doesn''t use ''em... the compiler is smart enough to remove it from your compiled code.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I had the same problem porting from Visual Studio .net to VC++ 6.

In light of this all I can say is that I agree with the others, using the " enum {...blah...} " syntax is probably your best bet.

Hey, there are about 7 different uses for the ''const'' keyword in C++, if I remember. As if one use isn''t confusing enough...

Anyway, I just wanted to post this for anyone using VS.net and having the same prob.

BTW, VS.net allows you to declare the same var type <name> multiple times:
i.e.
for (int i; blah; blah);
...code...
for (int i; blah; blah);
...code...
for (int i; blah; blah);
.
.
.

...as the Borland compiler does. Microsoft is learning...

-Q

"It appears you are living two lives [Mr. Anderson]."
- Mr. Smith (The Matrix)

Share this post


Link to post
Share on other sites
smart_idiot...what are you talking about?


  
class foo
{
public:
void bar(void) {}
foo() {}
};
int main(void)
{
const foo bar;
bar.bar(); // you can''t do this because the function might alter the object

return 0;
}


What is "const foo bar;"? And "bar.bar()", when bar is a member function of foo?

And this:

  
class foo
{
public:
mutable int bar;
foo(): bar(0) {}
};
int main(void)
{
const foo bar;
bar.bar = 4;
return 0;
}

Is the same thing...and that isn''t what mutable does. Mutable is used like this:


  
class foo
{
int a;
mutable int b;
public:
void DoSomething() const
{
a = 1; //wrong, this function is const, cant modify object

b = 2; //ok, since b was declared mutable

}
};

Share this post


Link to post
Share on other sites
Neosmyle: Smart_pointer is correct.
You can obviouly name a variable bar no matter if it has member functions called bar.
Secondly, his use of mutable is also correct. As is yours.
You are both doing the same thing.

DerekSaw: By 'use up memory', we mean space on the stack or the heap. Technically speaking, magic constants are not using up memory - they are part of the program instruction data. Of course you could say that it's using up memory because it appears in the program. But then you might as well say that the assembly instructions are also taking up memory.
quote:

p/s: And if you #define it, but doesn't use 'em... the compiler is smart enough to remove it from your compiled code.


If you don't use it, it would never replace anything. And therefore it would not be used. Similar thinking applies to enum, because it is a compile time constant, it is just compiled into the code - So there is no 'cost' to it.


-----------------------------
Gamedev for learning.
libGDN for putting it all together.

[edited by - risingdragon3 on November 18, 2002 11:59:43 PM]

Share this post


Link to post
Share on other sites