Const bypass in init method

Therefore, I cannot use initializers in my class constructor due to the use of arrays, so I decided to use the init() method. Now I have a different problem. I have a class like this:

 class EPWM { private: volatile EPWM_REGS* const regs; public: void init(volatile EPWM_REGS* _regs); }; 

where I need to implement init() by initializing regs = _regs; but I cannot because of const . Is there a way to force assignment in my init method? I would like to keep the const keyword, so I do not accidentally reassign elsewhere.

edit: as much as I would like to use a constructor + initializer that would solve this problem (my code used to do this), I cannot, because I have another class that has an array of EPWM objects, and I cannot initialize these objects because C ++ does not support initializers for array elements. (again, see another question I asked a little recently on this question. )

The context for using EPWM is something like this:

 class PwmGroup { private: EPWM *epwm; void init(EPWM *_epwm) { epwm = _epwm; } }; /* ... */ // main code: EPWM epwm[3]; PwmGroup pwmGroup; { // EPwm1Regs, EPwm2Regs, EPwm3Regs are structs // defined by TI include files for this processor epwm[0].init(&EPwm1Regs); epwm[1].init(&EPwm2Regs); epwm[2].init(&EPwm3Regs); pwmGroup.init(epwm); } 
+6
c ++ const
source share
5 answers

You can consider const_cast and pointers, but this is best used rarely. Something like...

 EPWM_REGS** regsPP = const_cast<EPWM_REGS**>(&regs); *regsPP = _regs; 
+4
source share

What about the next one?

 struct EPWM_array { EPWM_array() { /* initialize array */ } const EPWM *begin() const; const EPWM *end() const; EPWM array[ 10 ]; }; struct EPWMWrapper { volatile EPWM_REGS* const regs; EPWMWrapper(EPWM_array const& a) : regs(a.begin()) {} }; 
+1
source share

Maybe this will help? You can still intentionally violate the constitution, but it interferes with normal people stupid mistakes (I did not compile this).

 class EPWM { private: volatile EPWM_REGS* regs_for_init_never_use; volatile EPWM_REGS* const& regs; public: EPWM() : regs(regs_for_init_never_use) void init(volatile EPWM_REGS* _regs); }; 
+1
source share

Playing Devil's Advocate: besides the obvious intent of the document, since this is a private attribute, you cannot use the const keyword and not modify it separately from the init method.

Actually, const_cast can be undefined here, and of course I prefer not to run in those dark corners, no matter what workarounds.

 class EPWM { private: volatile EPWM_REGS* regs; // normally const, but need to be inited :/ public: void init(volatile EPWM_REGS* _regs); }; 

Although, repeat your question: while the raw array cannot be configured by default, you can write an array class, which may be.

 namespace detail { template <class T, size_t N, size_t index> struct At { static T& Do(Array<T,N>& array) { return At<T,N-1,index-1>::Do(array.tail()); } }; template <class T, size_t N> struct At<T,N,0> { static T& Do(Array<T,N>& array) { return array[0]; } }; template <class T, size_t index> struct At<T,0,index> {}; template <class T> struct At<T,0,0> {}; } // namespace detail template <class T, size_t N> class array { public: typedef T value_type; static const size_t Length = N; array(): mHead(), mTail() {} array(const array& rhs): mHead(rhs.mHead), mTail(rhs.mTail) {} // Don't know whether it will be optimized or not // Not sure I can use pointer arithmetic either :p T& operator[](size_t index) { return index == 0 ? mHead : mTail[index-1]; } // Compile time access template <size_t index> T& at() { return detail::At< T, N, index >::Do(*this); } private: T mHead; array<T, N-1> mTail; }; // class array<T,N> template <class T> class array<T,1> { public: typedef T value_type; static const size_t Length = 1; array(): mHead() {} array(const array& rhs): mHead(rhs.mHead) {} T& operator[](size_t index) { return mHead; } // or error handling ;) private: T mHead; }; // class array<T,1> template <class T> class array<T,0> {}; // int[0] does not work (stack) so... 

Ok ... maybe not as efficient as a real array ... you can always switch to preprocessor generation:

 template <class T> class Array4 { public: Array4(): m0(), m1(), m2(), m3() {} Array4(const Array4& rhs): m0(rhs.m0), m1(rhs.m1), m2(rhs.m2), m3(rhs.m3) {} T& operator[](size_t index) { return *(&m0 + index); } private: T m0; T m1; T m2; T m3; }; // class Array4<T> 
+1
source share

Use the constructor as follows:

 EPWM::EPWM(volatile EPWM_REGS* _regs) : regs(_regs) {} 

Then there are simply no parameters in init:

 void EPWM::init() { // do something with this->regs here... } 

In other words, you can initialize everything in the class constructor - just not member arrays.

0
source share

All Articles