0

I have a static const array class member (const pointers to SDL_Surfaces, but that's irrelevant), and have to loop through it in order to populate it. Aside from a const_cast when I'm done looping, which I hear is bad practice, how would I go about doing this?

EDIT: The reason I don't just do...

static SDL_Surface *const myArray[3];
...
class::myArray[3] = {...};

is that I need to read from a different array and run a function on the different array's respective value in order to get the value for this array. Once I've looped all the way through, I'm never changing this array again, so the way I see it, it should be const.

EDIT 2: I think I might have made a conceptual mistake here. Is it possible to const_cast in some way to make something const, instead of to remove it's constness, which is what I was trying to do? If not, then I was being a little silly asking this :D

Lewis
  • 1,310
  • 1
  • 15
  • 28
  • 1
    If you can't initialize the array with its final value then you can't make the array `const`. Perhaps you should give more detail about the problem that you are trying to solve? – CB Bailey Oct 11 '10 at 07:08
  • What are you populating it with? – JoshD Oct 11 '10 at 07:08
  • 1
    If an object is const, when you write to it you get undefined behavior. Period. You need to *initialize* it, not assign it. – GManNickG Oct 11 '10 at 07:13
  • I'm populating it with SDL_Surface* (pointers to image data, basically), which are based on the result of running load_image() on each item in turn of another list containing all the images filenames as strings. – Lewis Oct 11 '10 at 07:16
  • 2
    @Lewis: A better way to treat something as constant is to only provide non-mutating access to it. (That is, make this data private and provide a public accessor that returns a constant reference.) – GManNickG Oct 11 '10 at 07:22
  • @GMan: Now that you mention it, that makes a lot of sense in this instance. The array IS private, so I just need to make sure it doesn't get messed with by the object itself. I don't need to worry about external code needing access to the array. Thanks! – Lewis Oct 11 '10 at 07:28
  • @Lewis: Thanks. I've added it as an answer. – GManNickG Oct 11 '10 at 07:35

5 Answers5

3

If you're trying to initialize it, and if it's an array, just do it with an initialization list:

static const int myarray[] = {1,2,3,4,5,6};
JoshD
  • 12,490
  • 3
  • 42
  • 53
  • @Charles Bailey: I mean that it can't be done for an array of, say, Tractors. Am I wrong about this? I suspect it's possible with some knowledge of the class layout and much headache. I'd like to learn more if I'm mistaken. – JoshD Oct 11 '10 at 07:29
  • 1
    As long as `Tractors` has appropriate implicit constructors from the supplied initializers there's no reason that I know of that 'normal' array initialization shouldn't work. – CB Bailey Oct 11 '10 at 07:34
  • OK. In the case that the only constructors required two or more arguments, would there still be a way to write that? I'm just concerned about making an all encompassing statement that is incorrect. – JoshD Oct 11 '10 at 07:40
  • `struct test { test( int, int ) {} }; int main() { test array[2] = { test(1,2), test(3,4) }; }`. I have not tested, but I believe it should work (as long as `test` has a valid copy constructor. – David Rodríguez - dribeas Oct 11 '10 at 07:45
  • For constructors that take anything other than one parameter you need to construct a temporary value and copy that. Technically this requires the class to be copyable even though most compilers will eliminate the copy. – CB Bailey Oct 11 '10 at 07:49
  • @Charles Bailey @David: Thanks! I appreciate the clarification. Oddly, I had the exact same idea as David (even the names and parameters :) It's good to know. Again, thank you both for clarifying. – JoshD Oct 11 '10 at 09:01
3

If your array is const and you are using a const_cast to enable you to write values into it the you are invoking undefined behaviour.

This is almost universally not an acceptable practice.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
1
typedef boost::array< const SDL_Surface *, 100 > surfaces_t;

class A {
   static const surfaces_t surfaces;
};

surfaces_t initialize_surfaces()
{
   // ...
}

const surfaces_t A::surfaces = initialize_surfaces();

As for EDIT 2: You can't change the type of object after it is declared. Casts don't do that, it is not possible in C++. What casts do is to form an expression of a given type from an expression of another type, with appropriate semantics that are different for different types of casts. For const_cast, you can add/remove const and you can add/remove volatile, and nothing else.

usta
  • 6,699
  • 3
  • 22
  • 39
1

One method to provide "logical constness" is to make the data inaccessible, except by non-mutating means.

For example:

class foo
{
public:
    const bar& get_bar() { return theBar; }

private:
    static bar theBar;
};

Even though theBar isn't constant, since foo is the only thing that can modify it, as long as it does so correctly you essentially (logically) have a constant bar.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • As far as I can tell, this would be the best way to go about doing what I'm trying to do. Thanks! – Lewis Oct 11 '10 at 07:42
0

first of all, why do you need to change something that is declared constant ?

YeenFei
  • 3,180
  • 18
  • 26