0

I have structre with some const members:

struct Data {
  const bool a;
  const int b;
  float c;
};

const Data data = {/* initialization ... */};

const Data& GetData() {
  return data;
}

And I want to change sometimes this const members. Is there a way to convert/wrap Data to something struct that contains referecnes on const Data members but with removed const qualificator and allow me change them?

// Wrapper that allow modify const members
struct Wrapper {
   /*...*/
};

int main() {
  auto dataWrapper = Wrapper(GetData());
  dataWrapper.a = 123;
  dataWrapper.b = true;
  dataWrapper.c = 3.14f;

  return 0;
}
isrepeat
  • 113
  • 5
  • Why is `c` not const? is that intentional? – Jan Schultke Aug 16 '23 at 08:47
  • 5
    You cannot change something that is const, (if you do then your program has undefined behaviour). That's what const means. If you want to change something then don't make it const in the first place. – john Aug 16 '23 at 08:48
  • You can achieve something similar design-wise by making `Data` a class with private members and public getters, and `Wrapper` a friend of `Data` (possible accessing private setters in `Data`). – wohlstad Aug 16 '23 at 08:51
  • Obviously there is some reason that a) you made these fields const in the first place and b) why you then decided that you wanted to change them anyway. It would be better if you were to explain what those reasons are, that might allow you to get some useful help. – john Aug 16 '23 at 08:52
  • 1
    why make the members `const` in the first place? Make them non-const. If you need a `Data` with members that cannot be modified that is a `const Data` – 463035818_is_not_an_ai Aug 16 '23 at 08:57
  • Data is a public struct that initialized from JSON when program started. In most of cases you only can read members, but in some cases I need change this members (for example within friend classes). Const members can be rewritten only one by one use const_cast, but I'm looking for a way to transform the structure somehow to change its members. – isrepeat Aug 16 '23 at 09:05
  • 1
    Can't you return a "copy"/new object with changed values? – Jarod42 Aug 16 '23 at 09:06
  • 1
    @isrepeat *Const members can be rewritten only one by one use const_cast* No, they cannot. `const` value cannot be changed by any means, attempting to do so is Undefined Behaviour. See one example of what can happen: https://stackoverflow.com/questions/3593687/two-different-values-at-the-same-memory-address – Yksisarvinen Aug 16 '23 at 09:31
  • 1
    If you have a value that you "in some cases need to change", then it's a non-const. If you need to limit who can change them (do you *really* need to?), use access modifiers (`private`/`protected`) or provide interface(s) that only allow certain parties to modify the values. – Yksisarvinen Aug 16 '23 at 09:36
  • @Yksisarvinen "const_cast(GetData().b) = 123" will change "b" mebmer – isrepeat Aug 16 '23 at 09:37
  • 3
    @isrepeat **No, it doesn't**. It invokes Undefined Behaviour. A program that attempts to change a `const` value is **wrong** and compiler is allowed to do absolutely anything with such code. See the question I linked - the asker attempted to change a `const` variable and couldn't understand why the value was "changed" when accessing in one way and "not changed" when accessed in another. – Yksisarvinen Aug 16 '23 at 09:41
  • You could also change your struct to a class and create getter and setter methods for the values. The values a, b, c can then be private class members, so you can't access them from outside without the getter/setter method – Dario.Casciato Aug 16 '23 at 09:51
  • @Yksisarvinen, This does exactly what I want. I control where it was changing with using friend classes. In my case changing const members occure in start programm (in signletones) and in end (where no consumers use this data). – isrepeat Aug 16 '23 at 09:52
  • 4
    @isrepeat I'm not going to argue with you. If you modify `const` value, your program has Undefined Behaviour, period. Don't say you weren't warned when you spend two weeks on debugging some random piece of code to find out the bug is because of modifying a `const` in completely different place. – Yksisarvinen Aug 16 '23 at 09:58
  • 1
    `const` (and reference) member variables just suck, there's no way around it. You can use private non-const members with getters, or a single big getter for the whole struct. – HolyBlackCat Aug 16 '23 at 10:32
  • You could theoretically create an entirely unrelated `Wrapper` template class with all 3 members being non-const, but you cannot have this class: a) change the number of members automatically, if you add/remove members from `Data` b) change the names of member variables in `Wrapper`, if they change in `Data`... – fabian Aug 16 '23 at 16:13

1 Answers1

2

And I want to change sometimes this const members.

You cannot. Also const_cast cannot be used to modify something that is const. There is no way to modify something that is const.

What const_cast can do is the following:

  int x = 42;            // not const !!
  const int& ref = x;    // constant reference to x
  // ref = 0;            // not allowed, because ref is const
  int& mutable_ref = const_cast<int&>(ref);    // we know that ref refers to a non-const int
  mutable_ref = 0;       // ok, but only because x is not const

When the members are const you cannot modify them.

If you want to restrict modifications to some dedicated object you can use encapsulation:

struct data {
    friend class modifier;
    private:
        int value;
    public:
        int get() { return value; }
};

Nobody can modify the member. Only the friend can:

struct modifier {
    void modify(data& d,int value) { d.value = value; }
};

This only works when the data is not const. Once you have a const data or its member is const, it is constant. Constant means it cannot be modifed.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185