Locking a class member from modification

Hello,

I want to be able to store data into a data structure, and at some point I want to be able to get pointers to certain elements so that I can reference them directly without having to search. I need to ensure that in the data structure, nothing changes and the values don't somehow get shifted around in memory. I was wondering if there was a way to declare a class member as non const (so that I can read data into it, process, manipulate it as needed) but once I am done populating the data, lock the variable so that it remains unchanged. Thanks
> at some point I want to be able to get pointers to certain elements
> so that I can reference them directly without having to search.
> once I am done populating the data, lock the variable so that it remains unchanged

Make the functions which want to modify objects friends of the class, perhaps.

Another option is to make all the modifications, copy initialise a const qualified object which would be used thereafter, and discard the original mutable object.

If those are not feasible, implement a const lock flag and throw if modifications are attempted after the object is locked for modifications.

For instance:
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>
#include <string>
#include <stdexcept>

struct A
{
    int get_number() const { return i ; }
    const std::string& get_name() const { return str ; }

    int& number() { return non_const()->i ; }
    std::string& name() { return non_const()->str ; }

    void const_lock() { const_locked = true ; }

    private:
        int i = -9 ;
        std::string str = "anonymous" ;

        bool const_locked = false ;
        A* non_const()
        {
            if(const_locked) throw std::domain_error( "object is const locked: modifications are not allowed" ) ;
            return this ;
        }
};

int main()
{
    A a ;

    try
    {
        std::cout << a.number() << ' ' << a.name() << '\n' ;

        a.number() = 89 ;
        a.name() = "hello " ;
        a.name() += "world!!\n" ;
        std::cout << a.number() << ' ' << a.name() << '\n' ;

        a.const_lock() ;
        a.number() += 234 ; // throws
    }

    catch( const std::exception& e )
    {
        std::cerr << "*** error: " << e.what() << " *****\n\n" ;
    }

    std::cout << a.get_number() << ' ' << a.get_name() << '\n' ; // readable
}

http://coliru.stacked-crooked.com/a/77f07fd4a1d1ae9d
JLBorges,

I was thinking of making a wrapper class with a bool just like you mentioned. Is there a way to pass on a function call and arguments to a templated member. My thought was 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
26

template<class T>
class const_lock
{
  const_lock() : my_lock(false) {}

  // HOW TO IMPLEMENT SOMETHING LIKE THIS????
  template<typename...Args >
  auto operatorANY_OPERATOR (Args...args)
 {
    static_assert(my_lock == false, "Objected locked to modification");
    return my_value.ANY_OPERATOR(args);
 }

  // HOW TO IMPLEMENT SOMETHING LIKE THIS????
  template<typename...Args >
  auto ANY_METHOD(Args...args)
 {
    static_assert(my_lock == false, "Objected locked to modification");
    return my_value.ANY_METHOD(args);
 }

  private:
    bool my_lock;
    T my_value;
}


This would allow me a simple way to lock any object and still maintain all functionality. I'd also have to figure out how to allow const methods to pass this lock so only non-const methods require a check against my_lock. Any ideas?? Thanks
Last edited on
Wouldn't something like this suffice:

Header:
1
2
3
4
5
6
7
8
// ...
struct A
{
    int i = -9 ;
    // ...
};

extern const A& locked_a ; // in the interface, available to clients 


Implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ...
static A unlocked_a ; // used by the implementation; not visible outside

const A& locked_a = unlocked_a ;

void foo_implementation()
{
    unlocked_a.i += 100 ; // fine

    const A& locked_a = unlocked_a ;
    std::cout << locked_a.i << '\n' ; // fine

    // locked_a.i += 100 ; // *** error ***
}
That seems like it would work. The issue is that you need to have 2 objects of A allocated at the same time (even though you can destroy one later), and copy the data from one to another. This could be extremely inefficient for large data objects. Ideally, I don't want to allocate memory for or move my data once it is in the state I am happy with.
Last edited on
> The issue is that you need to have 2 objects of A allocated at the same time
> (even though you can destroy one later), and copy the data from one to another.

No. There is only one object static A unlocked_a ; in the above example.
locked_a is not an object; it is a reference: it is an alias for an object. (No copy is made.)
oh duh, didn't see that :)
Topic archived. No new replies allowed.