I hope I formulated the title a bit correct.
I have this base class
class FunctionBlock
{
public:
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
uint8_t Q_NOT : 1 ;
virtual void run() ;
} ;
And many subclasses like
class Or : public FunctionBlock // there is also And, JK, SR, NOT etc..
{
public:
Or()
{
IN1 = IN2 = IN3 = 0 ;
}
void run()
{
Q = IN1 | IN2 | IN3 ;
}
} ;
And the one with the problem:
class AnalogOutput : public FunctionBlock
{
public:
AnalogOutput( uint8_t _pin )
{
pin = _pin ;
}
void run()
{
if( analogIN2 != prevIn )
{ prevIn = analogIN2 ; // if incoming change, update PWM level
analogWrite( pin, analogIN2 ) ;
// Serial.println( analogIN2 ) ; // DEBUG just testing if it... actually works
}
}
uint8_t analogIN2 ; // I need to be 8 bits instead of 1 bit
private:
uint8_t pin ;
uint8_t prevIn ;
} ;
The main program process the logic of all function blocks and it updates the links. The links used to exist of a connection from a Q to an IN1, IN2 or IN3. Using bit fields I can stuff these in one single byte.
Now I have added analog components, so a single bit for Q and IN does not suffice. To solve this problem, I added the public variable analogIN2 as seen in the analogOutput class. Similarly I use a public variable int analogQfor an analog input.
For the links I make a destinction between digital and analog links.
Obivously I could change
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
Into
uint16_t IN1 ; // instead of 1 byte, I would need 8 bytes
uint16_t IN2 ;
uint16_t IN3 ;
uint16_t Q ;
But this would increase memory consumption, so I keep this as a last resort
#include "functionBlocks.h"
static AnalogInput b1 = AnalogInput(1) ;
static AnalogOutput b2 = AnalogOutput(5) ;
static And b3 = And() ;
static Or b4 = Or() ;
FunctionBlock *block[] = {
&b1 ,
&b2 ,
&b3 ,
&b4 ,
} ;
const int nBlocks = 4 ;
void setup()
{
}
void loop()
{
/***************** UPDATE FUNCTION BLOCKS *****************/
for( int i = 0 ; i < nBlocks ; i ++ ) block[i] -> run() ;
/***************** UPDATE LINKS *****************/
block[1] -> analogIN2 = block[0] -> analogQ ; // <-- analog link does not compile
block[3] -> IN2 = block[2] -> Q ; // digital links work fine
block[2] -> IN3 = block[3] -> Q ;
} ;
I marked the line which does not compile.
C:\Users\me\Documents\hobbyProjects\functionBloX\arduinoProgram\arduinoProgram.ino:26:17: error: 'class FunctionBlock' has no member named 'analogIN2'
block[1] -> analogIN2 = block[0] -> analogQ ;
The reason is obvious, the base class does not know about analogIn and analogQ. Therefor the array 'block[]' does not have acces to the members.
My questions:
Can I let the FunctionBlock *block[] objects give acces to analogQ without increasing memory usage drastically. And if so, how can I do that?
The one thing I could think of was to add a 2nd baseclass but I do not know every last in and out of c++, hence this question.
You could even go entirely without inheritance and polymorphism:
#include <tuple>
static auto blocks = std::make_tuple(AnalogInput(1), AnalogOutput(5), And(), Or());
void loop()
{
// Using the tuple elements as arguments to a suitable function
auto run_all = [](auto&... args) { (args.run(), ...); };
std::apply(run_all, blocks);
// Assuming that the digital and analog blocks now have members
// of the same name
auto& [b1, b2, b3, b4] = blocks;
b2.IN2 = b1.Q;
b4.IN2 = b3.Q;
b3.IN3 = b4.Q;
}
Admittedly, the interface of tuples is not as nice as that of arrays or other containers, but they are an option.
If all blocks have the same basic data, you could parametrise that using a template:
#include <concepts>
template<std::integral T = uint8_t, unsigned N = 1>
struct BlockData
{
T IN1 : N = 0;
T IN2 : N = 0;
T IN3 : N = 0;
T Q : N = 0;
T Q_NOT : N = 0;
};
You can also use your current approach, but then the data would need to be encapsulated behind virtual get/set functions:
struct FunctionBlock {
virtual ~FunctionBlock() = default;
virtual void run() = 0;
// Set channel 1 to the given value
virtual void in1(uint8_t) = 0;
// etc.
};
Related
I have a java program with which I create a program using logic function blocks. AND gates, OR gates that sorta things. This program can generate functional source code for an arduino board. This essentially allows people to program an Arduino with only logic gates.
The core essentials work but I am only halfway there and I run into a slight problem.
I have this struct and array
typedef struct blox
{
uint8_t IN1 : 1 ; // generic for most blocks
uint8_t IN2 : 1 ; // generic for most blocks
uint8_t IN3 : 1 ; // generic for most blocks
uint8_t Q : 1 ; // generic for most blocks
uint8_t pin : 5 ; // only inputs and output types need this
uint8_t type : 4 ; // 16 combinations
uint32_t oldTime ; // bad idea to use this amount of memory per block if only delays need it?
const uint32_t interval ; // perhaps couple a function pointers or obj pointer to it?
} FunctionBlock ;
FunctionBlock block [ nBlocks ] ;
In the main loop() I run all logic and I update the links. The links are hardcoded.
void loop()
{
/***************** UPDATE FUNCTION BLOCKS *****************/
for( int i = 0 ; i < nBlocks ; i ++ )
{
switch( block[i].type )
{
case AND:
block[i].Q = block[i].IN1 & block[i].IN2 & block[i].IN3 ; // unused inputs INx are initialized to '1'
break ;
case OR:
block[i].Q = block[i].IN1 | block[i].IN2 | block[i].IN3 ;
break ;
case M:
if( block[i].IN3 ) block[i].Q = 0 ; // R
else if( block[i].IN1 ) block[i].Q = 1 ; // S
break ;
case NOT:
block[i].Q = !block[i].IN2 ;
break ;
case INPUT_PIN:
block[i].Q = digitalRead( block[i].pin ) ;
break ;
case OUTPUT_PIN:
digitalWrite( block[i].pin, block[i].IN2 ) ;
break ;
case DEL: for( int i = 0 ; i < n_blocks ; i ++ )
{
if( block[i].Q != block[i].IN ) // if new state changes
{
if( millis() - block[i].oldTime >= block[i].interval ) // keep monitor if interval has expired
{
block[i].Q = block[i].IN ; // if so, adopt the new state
}
}
else
{
block[i].oldTime = millis() ; // if new state does not change, keep setting oldTime
}
}
break ;
}
}
/***************** UPDATE LINKS *****************/
block[3].IN2 = block[1].Q ; // hardcoded list of all links.
block[3].IN1 = block[0].Q ;
block[3].IN3 = block[2].Q ;
block[4].IN2 = block[3].Q ;
} ;
The problem is that the structure has variables for everything. Now AND and OR gates have a 'pin' variable and every block uses 8 bytes for timing, despite only the delay gate has need for it.
I also want to add analog (all that can be more than '0' or '1') components, like an analog input, servo motor, a map() block (to map one range into an other range), comparator contants etc.
Using the struct like this will consume way too much memory.
My best guess would be to use classes and inheritance. But I haven't used inheritance yet in c++ and I do not know how I can stuff objectes and derived objects in a single array.
class FunctionBlock // AND, OR, MEMORY or NOT gates
{
public:
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
uint8_t type ; // if I create derived classes for OR, AND, MEMORY and not gates, I may discard this variable
} ;
class IO : public FunctionBlock // INPUT, OUTPUT
{
uint8_t pin ;
} ;
class DELAY : public FunctionBlock
{
uint32_t prevTime ;
const int delayTime ;
} ;
class MAP : public FunctionBlock
{
int32_t var ; // result = map( var, in1, in2, out1, out2 ) ;
int32_t result
int32_t in1 ;
int32_t in2 ;
int32_t out2 ;
int32_t out2 ;
} ;
// class analogIn, class constant, class comperator, class decadeCounter etc etc
Were this Java I would simply do:
ArrayList <FunctionBlock> blocks = new ArrayList() ;
...
blocks.add( new AND( arguments ) ;
How do I get these derived classes to work in c++ ?
I think it might be better to define the separate structures without inheritance, and then use a union in the FunctionBlock structure to keep the data.
Perhaps something like this:
struct IO
{
uint8_t pin;
};
struct DELAY
{
uint32_t prevTime;
const int delayTime;
};
// ... the other structures...
struct FunctionBlock
{
// The current members of the structure...
union
{
IO io;
DELAY delay;
// ... and the other structures...
};
};
Then you can use e.g. block[i].io.pin to get the IO member pin.
Now you can just use the FunctionBlock structure as any other structure, and create a plain normal array.
I chose to go for inheritence as a union would not really solve the memory problem. And performance is in this case not really important. As in it does not matter if this program run 'efficient' or not.
I declare objects using the subclasses followed by a pointer array.
#include "functionBlocks.h"
static Input b1 = Input(1) ;
static Input b2 = Input(2) ;
static Input b3 = Input(3) ;
//static Or b4 = Or() ; // if I swap this Or gate for a Delay gate
static Delay b4 = Delay(2000) ; // RAM consumes 4 more bytes as anticipated.
static Delay b5 = Delay( 3000 ) ;
static Output b6 = Output(13) ;
FunctionBlock *block[] =
{
&b1,
&b2,
&b3,
&b4,
&b5,
&b6,
} ;
const int nBlocks = 6 ;
void setup()
{
}
void loop()
{
block[3] -> IN1 = block[0] -> Q ;
block[3] -> IN2 = block[1] -> Q ;
block[3] -> IN3 = block[2] -> Q ;
block[4] -> IN2 = block[3] -> Q ;
block[5] -> IN2 = block[4] -> Q ;
/***************** UPDATE FUNCTION BLOCKS *****************/
for( int i = 0 ; i < nBlocks ; i ++ ) block[i] -> run() ;
} ;
I tested the memory consumption by swapping out an OR gate for a DELAY and that increases memory usage by 4 bytes. This is correct because the DELAY uses one whole uint32_t variable on top the base class.
So using subclasses like this does resolve the memory problem.
If I now add a single OR gate, RAM only consumes five more bytes. One byte is used for the variables, IN1, IN2, IN3 and Q but I cannot place the other 4 bytes. I am guessing it is a function pointer to the appropiate run()method.
I also moved all the classes to a seperate header file. It looks as follows:
class FunctionBlock
{
public:
uint8_t IN1 : 1 ;
uint8_t IN2 : 1 ;
uint8_t IN3 : 1 ;
uint8_t Q : 1 ;
virtual void run() ;
} ;
class And : public FunctionBlock
{
public:
And()
{
IN1 = IN2 = IN3 = 1 ;
}
void run()
{
Q = IN1 & IN2 & IN3 ;
}
} ;
class Or : public FunctionBlock
{
public:
Or()
{
IN1 = IN2 = IN3 = 0 ;
}
void run()
{
Q = IN1 | IN2 | IN3 ;
}
} ;
class Delay : public FunctionBlock
{
public:
Delay(int x) : delayTime( x ) // initialize the constant
{
}
void run()
{
if( Q != IN2 ) // if new state changes
{
if( millis() - prevTime >= delayTime ) // keep monitor if interval has expired
{
Q = IN2 ; // if so, adopt the new state
}
}
else
{
prevTime = millis() ; // if new state does not change, keep setting oldTime
}
}
private:
const uint32_t delayTime ;
uint32_t prevTime ;
} ;
I have written a libary for somebody else to slowly sweep servo's from one position to another. It did not work like I intented and I had to remove the servo objects from the library. Instead I let the new version calculate the servo positions and return those values instead. Yet I really like to know why it is not working.
The header file with the private Servo objects
#include <Arduino.h>
#include <Servo.h>
class ServoSweep {
public:
ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed ) ; // constructor 1
ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed, byte _relayPin ) ; // constructor 2
void sweep( );
void setState( uint8_t _state );
private:
Servo servo ;
unsigned long timeToRun ;
byte pos ;
byte state ;
byte prevPos;
byte servoPin ;
byte servoSpeed ;
byte servoMin ;
byte servoMax ;
byte middlePosition ;
byte relayPresent ;
byte relayPin ;
} ;
And the source file:
#include "ServoSweep.h"
ServoSweep::ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed ) { // constructor 1
servoPin = _servoPin ;
servoSpeed = _speed ;
servoMin = _min ;
servoMax = _max ;
middlePosition = ( (long)servoMax - (long)servoMin ) / (long)2 + (long)servoMin ; // start with middle position
pos = middlePosition ;
servo.write( pos ) ;
servo.attach( servoPin ) ;
}
ServoSweep::ServoSweep( byte _servoPin, byte _min, byte _max, byte _speed, byte _relayPin ) { // constructor 2
servoPin = _servoPin ;
servoSpeed = _speed ;
servoMin = _min ;
servoMax = _max ;
middlePosition = ( (long)servoMax - (long)servoMin ) / (long)2 + (long)servoMin ;
pos = middlePosition ;
servo.write( pos ) ;
servo.attach( servoPin ) ;
relayPresent = 1;
relayPin = _relayPin ;
pinMode( relayPin, OUTPUT ) ;
}
void ServoSweep::sweep () {
if( millis() > timeToRun ) {
timeToRun = millis() + servoSpeed ;
if( state ) {
if( pos < servoMax ) pos ++ ;
}
else {
if( pos > servoMin ) pos -- ;
}
if( prevPos != pos ) {
prevPos = pos ;
if( relayPresent == 1 ) {
if( pos < middlePosition ) digitalWrite( relayPin, LOW ) ;
else digitalWrite( relayPin, HIGH ) ;
}
servo.write( pos ) ;
}
}
}
void ServoSweep::setState( uint8_t _state ) {
state = _state ;
}
The servo signal was complete jitter caused by the arduino. The example sketch I used:
#include "ServoSweep.h"
const int inputButton = 12 ;
const int servoPin1 = 2 ;
const int servoPin2 = 3 ;
unsigned long prev ;
byte state ;
// pin min max speed (bigger speed = slower movement ;
ServoSweep servo1(servoPin1, 10, 30, 50) ;
ServoSweep servo2(servoPin2, 10, 30, 50) ;
void setup() {
pinMode( inputButton, INPUT_PULLUP ) ;
}
void loop() {
servo1.sweep();
servo2.sweep();
if( digitalRead( inputButton ) ) servo1.setState( 1 ) ;
else servo1.setState( 0 ) ;
if( digitalRead( inputButton ) ) servo2.setState( 0 ) ;
else servo2.setState( 1 ) ;
}
Even I comment out al code inside the loop, the jitter is there. The jitter starts as soon as I construct the ServoSweep objects.
What did I wrong with the servo objects? I assume this has to be possible.
The problem is most likely in your constructor. These lines:
servo.write( pos ) ;
servo.attach( servoPin ) ;
in the constructor are trying to work with hardware that may not be ready yet. You are calling the constructor at global scope, so these things may be happening before init() runs and sets up the hardware. So when init() does run, it is probably overwriting values that the servo library had written to timer 1.
This is a common issue and a common newbie trap. Constructors should initialize variables and set up values and things, but they are not for handling hardware. For that you need a begin() or init() method that you can call from setup. Think about how the servo library has the attach function that you have to call from setup. If it were possible to do that in the constructor, they would have had the constructor take the pin number and do it. Think about the begin method that you have to call for Serial to work. That's the same story, there's hardware to setup and you need to be able to control when that happens.
So make one more method:
void ServoSweep::begin() {
servo.write( pos ) ;
servo.attach( servoPin ) ;
}
And call that from setup for each object and remove those lines from the constructor.
I have written a debounce class to debounce inputs.
The idea was that a state of a certain input may be ON, OFF, FALLING or RISING.
the object.debounceInputs() is to be called with a fixed interval
With the the function object.readInput() the correct state of the object could be read in. A FALLING or RISING state only lasts for 1 interval time (usually set at 20ms) and these states can only be read once.
Ofcourse I tested the software and it worked without flaw, now I started using the software in other projects and a peculiar bug came to light.
The software works perfectly fine... if you have just one input object. If you debounce more than 1 object, the inputs are affecting each other which should not be possible as every object uses private variables.
The source code:
#include "debounceClass.h"
Debounce::Debounce(unsigned char _pin) {
pinMode(_pin, INPUT_PULLUP); // take note I use a pull-up resistor by default
pin = _pin;
}
unsigned char Debounce::readInput() {
byte retValue = state;
if(state == RISING) state = ON; // take note I use a pull-up resistor
if(state == FALLING) state = OFF; // rising or falling may be returned only once
return retValue;
}
void Debounce::debounceInputs() {
static bool oldSample = false, statePrev = false;
bool newSample = digitalRead(pin);
if(newSample == oldSample) { // if the same state is detected atleast twice in 20ms...
if(newSample != statePrev) { // if a flank change occured return RISING or FALLING
statePrev = newSample ;
if(newSample) state = RISING;
else state = FALLING;
}
else { // or if there is no flank change return PRESSED or RELEASED
if(newSample) state = ON;
else state = OFF;
}
}
oldSample = newSample;
return 255;
}
The corresponding header file:
#include <Arduino.h>
#ifndef button_h
#define button_h
//#define
#define ON 9 // random numbers, RISING and FALLING are already defined in Arduino.h
#define OFF 10
class Debounce {
public:
Debounce(unsigned char _pin);
unsigned char readInput();
void debounceInputs();
private:
unsigned char state;
unsigned char pin;
};
#endif
I have had this bug with 2 separate projects, so the fault definitely lies in my Debounce class.
An example program to illustrate the program:
#include "debounceClass.h"
const int pin3 = 3 ;
const int pin4 = 4 ;
Debounce obj1( pin3 ) ;
Debounce obj2( pin4 ) ;
byte previousState1, previousState2;
unsigned long prevTime = 0, prevTime1 = 0, prevTime2 = 0;
void setup()
{
Serial.begin( 115200 ) ;
// CONSTRUCTOR OF OBJECTS SETS THE PINMODE TO INPUT_PULLUP
pinMode( pin3, OUTPUT ) ;
pinMode( pin4, OUTPUT ) ;
}
const int interval = 20, interval1 = 1000, interval2 = 2000;
void loop() {
unsigned long currTime = millis() ;
if( currTime > prevTime + interval ) {
prevTime = currTime ;
obj1.debounceInputs(); // comment one of these 2 out, and the other debounces perfectly
obj2.debounceInputs();
#define printState(x) case x: Serial.print(#x); break
byte state = obj1.readInput() ;
if( state != previousState1 ) {
previousState1 = state ;
Serial.print("state of obj1 = ") ;
switch ( state ) {
printState( ON ) ;
printState( OFF ) ;
printState( RISING ) ;
printState( FALLING ) ;
}
Serial.println();
}
state = obj2.readInput() ;
if( state != previousState2 ) {
previousState2 = state ;
Serial.print("state of obj2 = ") ;
switch ( state ) {
printState( ON ) ;
printState( OFF ) ;
printState( RISING ) ;
printState( FALLING ) ;
}
Serial.println();
}
}
if( currTime > prevTime1 + interval1 ) {
prevTime1 = currTime ;
digitalWrite( pin3, !digitalRead( pin3 ) );
}
if( currTime > prevTime2 + interval2 ) {
prevTime2 = currTime ;
digitalWrite( pin4, !digitalRead( pin4 ) );
}
}
This program automatically toggles both pins so you do not need physical inputs. If you comment out one of the indicated lines, you'll see that the other pin is debounced just fine. But when both pins are debounced the result is catastrophic. There is a weird link between the 2 objects which I cannot explain. I have reached a point at which I start doubting the compiler, so that was the moment I realized that I need to ask others.
Why is this happening and what did I do wrong here?
I found the problem.
I cannot use a static variable within a class method. These static variables are seen by all objects which caused the problem.
I moved the static variables to the private variable section
I used DrawItem() to redraw my CListbox. For some reasons, I want to use custom compare to sort my list item with my own rules, and I use LBS_SORT and no LBS_HASSTRING properties. After using SetItemData() in OnInitDialog(), I get these data in DrawItem(), but it didn't work. Code is like below:
init code :
void OnInitDialog(...)
{
.........
m_List.SetListHeight (40);
for (int i = 0 ; i < 20 ; i ++) {
m_List.AddString ((const char *) i);
m_List.SetItemData (i,(100 + i));
}
....
}
compare code :
int CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
{
ASSERT(lpCompareItemStruct->CtlType == ODT_LISTBOX);
int a = lpCompareItemStruct->itemData1;
int b = lpCompareItemStruct->itemData2;
return (a - b);
}
redraw code :
DrawItem (lpDIS)
{
..................
CString str;
int i = (int) GetItemData (lpDIS->itemID); // the i is not what I expect.
str.Format ("%d", (int) i);
dc.DrawText (str,CRect (&lpDIS->rcItem), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
...................
}
when I use
***index = m_List.addstring ((const char *) i) ;
m_List.setitemdata (index,(100 + i));***
it works ,but if I use a struct to addstring ,the index is not right ,code is like this below :
struct test {
int a,b,c,d;
};
init_code :
test *ptest = new test[20]; /* just a test ,we don't delete memory till application ends */
for (int i = 0 ; i < 20 ; i ++) {
ptest [i].a = i;
int index = m_List.AddString ((const char *) (ptest + i));
m_List.SetItemDataPtr (index,(void *) (100 + i));
}
compare code :
int ListEx::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
{
// TODO: Add your code to determine the sorting order of the specified items
// return -1 = item 1 sorts before item 2
// return 0 = item 1 and item 2 sort the same
// return 1 = item 1 sorts after item 2
// ASSERT(lpCompareItemStruct->CtlType == ODT_LISTBOX);
test *pa,*pb;
pa = (test *) lpCompareItemStruct->itemData1; // crashed here
pb = (test *) lpCompareItemStruct->itemData2;
// ASSERT (pa);
// ASSERT (pb);
return (pa->a - pb->a);
}
draw_item code :
CString str;
test *ptest = (test *) (lpDIS->itemData);
str.Format ("%d", (int) ptest->a);
dc.DrawText (str,CRect (&lpDIS->rcItem), DT_CENTER | DT_VCENTER | DT_SINGLELINE);
Is addstring can only use strings ???
if the item is a struct data ,how could I set these struct data to the listbox item ???
In OnInitDialog you should do this:
for (int i = 0 ; i < 20 ; i ++) {
int index = m_List.AddString ((const char *) i);
m_List.SetItemData (index, 100 + i);
}
AddString returns the index where the item has been inserted (which can be anywhere if the list is sorted). m_List.SetItemData (index ,(100 + i)) sets the data for the item you just have inserted.
we can set structure data to list box.
struct _empInfo {
CString strName;
..............
} empInfo = {L"XYZ",...};
m_list.AddString(empinfo.strName);
I tried above code in my app..
This is sort of a design doubt .
Scenario: I have an array which contain some integer elements . This array is populated by 1 module (.so) in my code base say X. It is then shared to another module say Y (.so) . At run time X module identifies that module Y would need to work on few fields of the array and modify it and that was the reason X shared the array to Y . ( Both these so are consumed into one binary .)
Once Y returns the module X prints the array .
Problem : How can I enforce programatically that module Y does not modify any other array index other than the one identified by X . SInce the whole array is passed between modules i cant make it const as then Y would not be able to change any field . You can say i want to enforce const-ness for few fields identified at run time .
How about this:
template <class T> class CProtectedArray {
private:
T* m_aItems;
unsigned int* m_aMask;
public:
CProtectedArray(int cElem, bool fInitialProtect) : m_aItems(NULL) {
int cbElem = sizeof(T)*cElem;
int cbMask = sizeof(int)*(cElem+31)/32;
m_aItems = (T*)malloc(cbElem + cbMask);
m_aMask = (unsigned int*)(m_aItems + cElem);
memset(m_aItems, 0, cbElem);
memset(m_aMask, fInitialProtect ? -1 : 0, cbMask);
}
~CProtectedArray() {
if (m_aItems)
free(m_aItems);
}
bool IsProtected(int iItem) { return !!(m_aMask[iItem>>5] & (1<<(iItem&31))); }
void Protect(int iItem) { m_aMask[iItem>>5] |= 1<<(iItem&31); }
void UnProtect(int iItem) { m_aMask[iItem>>5] &= ~(1<<(iItem&31)); }
void Set(int iItem, T val) {
if (!IsProtected(iItem))
m_aItems[iItem] = val;
}
};
int main(int argc, char* argv[])
{
CProtectedArray<int> A(100, true);
bool f = A.IsProtected(30); // f = true
A.Set(30, 23); // nothing happens
A.UnProtect(30);
f = A.IsProtected(30); // f = false
A.Set(30, 24); // sets element 30 to 24
A.Protect(30);
f = A.IsProtected(30); // f = true
A.Set(30, 25); // nothing happens
}