Modern language like C# allow for specifying setting and getting methods/logic for bracket [] operators, as well as multi-index bracket operators. C++ does not offer these features natively. Fortunately, these capabilities can be added without changing the external signatures/code what-so-ever.
Let's assume you have a simple Threshold array, which stores values between a min and max.
They way it should work, is that values higher are stored as the max, and values lower are stored as the min.
Let's implement it the "old" way, leaving a TODO
to add logic.
// ThresholdArray.hpp
#ifndef THRESHOLD_ARRAY_H
#define THRESHOLD_ARRAY_H
#include <stdlib.h>
template<typename T>
class ThresholdArray {
public:
ThresholdArray(unsigned int size, T max, T min) {
this->size = size;
this->max = max;
this->min = min;
values = (T*)malloc(size * sizeof(T));
for (int n = 0; n < size; n++) { values[n] = min; }
};
~ThresholdArray() { free(values); values = NULL; };
T & operator[](unsigned int i) {
// TODO: add get/set logic
return values[i % size];
};
void Print() {
printf("(%d, %0.2f, %0.2f)\t: {", size, max, min);
for (int n = 0; n < size - 1; n++) { printf("%0.2f, ", values[n]); }
printf("%0.2f}\n", values[size - 1]);
};
private:
unsigned int size = 0;
T max;
T min;
T* values;
};
// A specialization of Print for integers
template<>
void ThresholdArray<int>::Print()
{
printf("(%d, %d, %d)\t: {", size, max, min);
for (int n = 0; n < size - 1; n++) { printf("%d, ", values[n]); }
printf("%d}\n", values[size - 1]);
}
#endif // THRESHOLD_ARRAY_H
We'll have to test out this class using a main() method.
#include "ThresholdArray.hpp"
int main()
{
// Make a ThresholdArray
ThresholdArray<float> arr = ThresholdArray<float>(8, 6.0, 0.0);
// Make a more limiting array
ThresholdArray<int> arn = ThresholdArray<int>(8, 5, 1);
for (int n = 0; n < 8; n++) {
arr[n] = n;
arn[n] = arr[n];
}
// Display the arrays
arr.Print();
arn.Print();
getchar();
return 0;
}
Running the initial main function produces the following code.
(8, 6.00, 0.00) : {0.00, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00}
(8, 5, 1) : {0, 1, 2, 3, 4, 5, 6, 7}
As expected, the ThresholdArray does not work as desired. There are some incorret values in the arrays that are outside of the desired bounds. Fortunately, this can be fixed by adding a class to wrap the values, which we call ThresholdValue. The header file is updated as follows:
//ThresholdArray.hpp
#ifndef THRESHOLD_ARRAY_H
#define THRESHOLD_ARRAY_H
#include <stdlib.h>
template<typename T>
class ThresholdValue {
public:
ThresholdValue(T* value, T max, T min)
{this->value = value; this->max = max; this->min = min; }
operator T() const { return *value; }
void operator = (const T val) {
if (val > max) { *value = max; }
else if (val < min) { *value = min; }
else { *value = val; }
}
private:
T max;
T min;
T* value;
};
template<typename T, unsigned int size, T max, T min>
class ThresholdArray {
public:
ThresholdArray(unsigned int size, T max, T min) {
this->size = size;
this->max = max;
this->min = min;
values = (T*)malloc(size * sizeof(T));
for (int n = 0; n < size; n++) { values[n] = min; }
};
~ThresholdArray() { free(values); values = NULL; };
ThresholdValue<T> operator[](unsigned int i) {
// A little pointer math to pass the value pointer
return ThresholdValue<T>(values + (i % size), max, min);
};
void Print() {
printf("(%d, %0.2f, %0.2f)\t: {", size, max, min);
for (int n = 0; n < size - 1; n++) { printf("%0.2f, ", values[n]); }
printf("%0.2f}\n", values[size - 1]);
};
private:
unsigned int size = 0;
T max;
T min;
T* values;
};
// A specialization of Print for integers
template<>
void ThresholdArray<int>::Print()
{
printf("(%d, %d, %d)\t: {", size, max, min);
for (int n = 0; n < size - 1; n++) { printf("%d, ", values[n]); }
printf("%d}\n", values[size - 1]);
}
#endif // THRESHOLD_ARRAY_H
Without any modifications to the main() function, it returns the following output:
(8, 6.00, 0.00) : {0.00, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 6.00}
(8, 5, 1) : {1, 1, 2, 3, 4, 5, 5, 5}
Everything seems to be working in the ThresholdArray class. Using the value wrapper, set and get logic can be added (in C++) without any changes to the code's signature.