Reputation: 4920
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
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
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
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
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