cast away const?

Hey,

As far as i know casting away const is a bad idea, but what about the following example?

Lets say I'm using a framework which returns me the width of a mobile device(width differs from device to device)

At the class construction the width isn't calculated (so i can't init the correct calculated value in the initiaizer list), but the framework offers a OnInit() method and at this point the GetWidth() method returns the correct device width.

Now to the problem:

I need the device width to calculate a specific int value which should never change after the OnInit(), would it still be bad to make the int value const, cast its const away inside the OnInit(), but the const remains in the rest of the class?

test code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.h
const int value;

.cpp
MyClass::MyClass()
: value(20)
{}

void MyClass::OnInit()
{
  //cast const away here
  int* tmp = (int*) &value;
  *tmp = //calculate value & GetWidth();

  //but value remains const to prevent changes
}
Last edited on
I think it's a reasonable idea, but I have never seen anyone use const in that way before. Personally, I wouldn't make value const.

The way to do this with C++ casts is:
 
int* tmp = const_cast<int*>(&value);
Results of changing a variable which was originally const are undefined.

Most common problem you might run into is that changes to that variable are not visible:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

struct foo
{
    const int width = 0;
    void init()
    {
        const_cast<int&>(width) = 10;
    }
    int getW() { return width;}
};

int main()
{
	foo x;
	x.init();
	std::cout << x.getW();
}
Might yield 0 in output as getW might be optimized to simply return 0;
Last edited on
So there exists a period of time between the constructor completing and the invocation of OnInit(). Is the object in a valid state during this time? Is there any way to fetch this information before calling the constructor? Needing to const cast your way around it is a suspicious code smell.
Last edited on
OnInit is called much later, but it's the only method which is called before the rest of the class is used and where the GetWidth() returns the correct value.

So removing const is the better way here?
Just thought it wouldn't be a bad idea to have it const, to tell other programmers it shouldn't be changed in the rest of the code.
Well, you can use type which can be assigned value only once. Like that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>

template <typename T>
class init_once
{
	public:
	operator=(const T& other)
	{
		if(!initialized) {
			initialized = true;
			value = other;
		} else {
		    throw "Value initialized twice";
		}
	}
	operator const T&()
	{
		if(!initialized)
			throw "Uninitialized value used";
		return value;
	}
private:
	T value;
	bool initialized = false;
};


struct foo
{
    init_once<int> width;
    void init()
    {
        width = 10;
    }
    int getW() { return width;}
};

int main()
{
	try{
	foo x;
	//std::cout << x.getW() << '\n';
	x.init();
	std::cout << x.getW() << '\n';
	//x.init();
	std::cout << x.getW() << '\n';
	} catch(const char* c) {
		std::cout << c;
	}
}
(uncomment lines to see errors which arise because of incorrect use)

Or have a nonconst value somewhere, but have class refer to it by const reference/pointer. As long as it is originally non-const, const cast is safe.
> So removing const is the better way here?
> Just thought it wouldn't be a bad idea to have it const, to tell other programmers it shouldn't be changed

No. Consider declaring the object as const volatile (access to it would be somewhat slower).

Something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct base
{
    public: virtual void on_init() ;

    // ...
};

struct my_class : base
{
    int value() const { return v ; }


    private: virtual void on_init() override
    {
        base::on_init() ;

        int computed_value = 0 ;
        // compute the value
        // ...

        const_cast< volatile int& >(v) = computed_value ; // cast away constness, but retain volatility
    }

    private: const volatile int v = -1 ; // v is a const-volatile object (it is not a const object)
};


The IS makes a clear distinction between a const object and a const volatile object.
for my example above this would be fine?:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.h
const volatile int value;

.cpp
MyClass::MyClass()
: value(20)
{}

void MyClass::OnInit()
{
  //cast const away here
  const_cast< volatile int& >(value) = GetWidth() * ......(calculate someth)........ ;

}
Last edited on
Do not use const in this case. The nature of a constant is that it never changes.

Before OnInit() it has the value 20 and after this another value.
A user of your class cannot expect this behavior and hence it's a clear design error.

Just admit that it isn't const and use private in order to reduce the accessibility of the variable.
its just a example,
a const variable must be initialized in the initializer list as far as i know .value(20) is a bad example, value(0) would be a bit better :o

In my project it's ofc private.
why can't you write GetWidth() * (calculate someth) in the initializerlist?
Last edited on
> for my example above this would be fine?:

I would suggest something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//////////// .h /////////////

struct my_class
{
    // returns -1 if value is not yet established
    // once the value is established, the same value is returned for every 
    // call after that. if the call overhead is a concern, the first 
    // (established) value that was returned may be safely cached and reused.
    int value() const ;

    // value() is established after the first call to on_init()
    // mandatory if access is public: the function is idempotent
    void on_init() ; 

    // ...
};


///////////// .cpp /////////

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace // internal linkage
{
    // not programmatically visible outside this translation unit
    const volatile int the_value = -1 ;
}

int my_class::value() const { return the_value ; }

void my_class::on_init()
{
    // ...
    
    const_cast< volatile int& >(the_value) = whatever ;
    
    // ...
}
@Gamer2015 GetWidth() doesn't return the correct width at the construction of this class.

@JLBorges
hmm, why is this a better approach than just having a private const volatile value in the class?
> why is this a better approach than just having a private const volatile value in the class?

You need a value to be a non-static member object of the class only if the value can vary from instance to instance. The width of the mobile device is the same for every instance, isn't it?
(My mistake; I should have written static int value() ;).

A private member of the class would be programmatically visible throughout the entire program.
A name with internal linkage (at global namespace scope) is visible only within the component that has the name.

With a private non-static const volatile member object, many optimisations are inhibited: for instance copy-elision.

Restrict visibility of names to the extent possible:
Ergo, a global object with internal linkage is preferable to a private static member object.

Localise the preservation of invariants to the extent possible:
Ergo, a private static member object is preferable to a global object with external linkage.
GetWidth() doesn't return the correct width at the construction of this class.
Do you know the value when creating the object?
If you want to have a const member then the Object it should be initialized at the start, otherwise it shouldn't be declared a const member.

Would you mind showing a bit more information?
Like, the things needed to initialize the variable and the reason why it can't be known when creating the object?
Without discussing whether or not it is the best option, consider the "mutable" keyword which allows data members of a const-qualified class object to be modified without casting.

Mutable members are often used to cache values within an object so they do not need to be calculated every time they are used.
Without discussing whether or not it is the best option, consider the "mutable" keyword which allows data members of a const-qualified class object to be modified without casting.
This is not a valid alternative because he wants the parameter itself to be const (even in non-const-qualified classes).
he wants the parameter itself to be const

actually i'm asking you guys if its a good idea at all :P, or if there is a better solution :)
actually i'm asking you guys if its a good idea at all
In general I'd say you should make const whenever possible and logical.
In your case I'd say yes, you should try to make it const.

But you should be able to make it const without using the OnInit method IMO.
What happens between construction and the OnInit method?
To me, this is a design issue. The real question is:

Why are you creating the object at a point where you're not able to properly initialize its state? Why not wait until you're actually able to get all the data you need, before creating the object?
Topic archived. No new replies allowed.