Vektor88
Vektor88

Reputation: 4920

struct with const member

I'm having some trouble with a template struct.

template<typename T>
struct A{
    const int v1;
    T* v2;
};

My purpose is to make v1 always not editable, while v2 should be editable if I use T and not editable if I use const T as type.

If I create constructor to initialize A, the struct becomes:

template<typename T>
struct A{
    const int v1;
    T* v2;
    A() : v1(-1) { v2=NULL; }
    A(int value) : v1(value) { v2=NULL; }
};

But then g++ says that I need a specific assignment operator:

error: non-static const member ‘const int A::v1’, can’t use default assignment operator

But my assignment operator should also allow editing of v1. The only thing I'd like to avoid is an edit from the outside, something like:

A a;
a.v1=10;

Is there any way to implement this (without creating getter/setter or using a pointer to a new A(int) with the desired value)?

What if I declare v1 as a const int * ? It could refer someway to some value, but it cannot edit it.

Upvotes: 3

Views: 29556

Answers (4)

Steve Jessop
Steve Jessop

Reputation: 279265

Here's a way to "expose" a public, read-only data member that is modifiable by the class's own member functions (including assignment):

template <typename T>
class Helper {
    friend class A;
    T *ptr;
    Helper &operator=(const Helper &rhs) = default; // in C++11
    Helper &operator=(const Helper &rhs) { ptr = rhs.ptr; } // in C++03
  public:
    Helper(T *ptr) : ptr(ptr) {}
    operator const int &() const { return *ptr; }
};

class A {
    int v1_;
  public:
    Helper<int> v1;
    A() : v1(&v1_) {} // although `A` should have a constructor that sets `v1_`
    A(const A &rhs) { v1_ = rhs.v1_; v1 = Helper<int>(&v1_); }
    A &operator=(const A &rhs) { v1_ = rhs.v1_; v1 = Helper<int>(&v1_); }
};

Now anyone outside the class A can use v1, but the only thing they can use it for is to get a const int& reference to v1_.

It is far easier just to give A a getter function that returns const int &, but if you really want the data member syntax then this provides it...

Upvotes: 3

Vektor88
Vektor88

Reputation: 4920

I solved my problem by changing the type of v1 from int to const int *, by doing this I can change the address of v1 and consequently change the value that v1 points to, but preventing any kind of editing.

So, here's my new simple struct

template<typename T>
struct A{
    const int* v1;
    T* v2;
};

When I use A with type T, I let v2 to be edited, and when I use A with type T const I prevent any attempt to edit v2's pointed value.

Upvotes: 0

pmr
pmr

Reputation: 59811

It says that you cannot use the default assignment operator. Nothing keeps you from writing your own operator= and use a const_cast. Unfortunately, this will be undefined behavior as v1 is declared const. So I'd suggest that you use accessors and private data.

Upvotes: 2

Martin Beckett
Martin Beckett

Reputation: 96109

You could just make it a class with everything public (thats all a struct is) and use an initialisation list - no need for getters/setters

Upvotes: 1

Related Questions