Вот некоторый код, который реализует то, что вы запрашиваете, за исключением того, что нижняя граница зафиксирована на 0. Он также показывает редкий вариант использования для оператора address_of. Вы можете пойти дальше и сделать этот контейнер совместимым с алгоритмами STL, если хотите.
#include <iostream>
#include <limits.h>
#include <stddef.h>
template<class T, size_t WIDTH, size_t SIZE>
class UserArray;
template<class T, size_t WIDTH, size_t SIZE>
class UserArrayProxy;
template<class T, size_t WIDTH, size_t SIZE>
class UserArrayAddressProxy
{
public:
typedef UserArray<T, WIDTH, SIZE> array_type;
typedef UserArrayProxy<T, WIDTH, SIZE> proxy_type;
typedef UserArrayAddressProxy<T, WIDTH, SIZE> this_type;
UserArrayAddressProxy(array_type& a_, size_t i_) : a(a_), i(i_) {}
UserArrayAddressProxy(const this_type& x) : a(x.a), i(x.i) {}
proxy_type operator*() { return proxy_type(a, i); }
this_type& operator+=(size_t n) { i += n; return *this; }
this_type& operator-=(size_t n) { i -= n; return *this; }
this_type& operator++() { ++i; return *this; }
this_type& operator--() { --i; return *this; }
this_type operator++(int) { this_type x = *this; ++i; return x; }
this_type operator--(int) { this_type x = *this; --i; return x; }
this_type operator+(size_t n) const { this_type x = *this; x += n; return x; }
this_type operator-(size_t n) const { this_type x = *this; x -= n; return x; }
bool operator==(const this_type& x) { return (&a == &x.a) && (i == x.i); }
bool operator!=(const this_type& x) { return !(*this == x); }
private:
array_type& a;
size_t i;
};
template<class T, size_t WIDTH, size_t SIZE>
class UserArrayProxy
{
public:
static const size_t BITS_IN_T = sizeof(T) * CHAR_BIT;
static const size_t ELEMENTS_PER_T = BITS_IN_T / WIDTH;
static const size_t NUMBER_OF_TS = (SIZE - 1) / ELEMENTS_PER_T + 1;
static const T MASK = (1 << WIDTH) - 1;
typedef UserArray<T, WIDTH, SIZE> array_type;
typedef UserArrayProxy<T, WIDTH, SIZE> this_type;
typedef UserArrayAddressProxy<T, WIDTH, SIZE> address_proxy_type;
UserArrayProxy(array_type& a_, int i_) : a(a_), i(i_) {}
this_type& operator=(T x)
{
a.write(i, x);
return *this;
}
address_proxy_type operator&() { return address_proxy_type(a, i); }
operator T()
{
return a.get(i);
}
private:
array_type& a;
size_t i;
};
template<class T, size_t WIDTH, size_t SIZE>
class UserArray
{
public:
typedef UserArrayAddressProxy<T, WIDTH, SIZE> ptr_t;
static const size_t BITS_IN_T = sizeof(T) * CHAR_BIT;
static const size_t ELEMENTS_PER_T = BITS_IN_T / WIDTH;
static const size_t NUMBER_OF_TS = (SIZE - 1) / ELEMENTS_PER_T + 1;
static const T MASK = (1 << WIDTH) - 1;
T operator[](size_t i) const
{
return get(i);
}
UserArrayProxy<T, WIDTH, SIZE> operator[](size_t i)
{
return UserArrayProxy<T, WIDTH, SIZE>(*this, i);
}
friend class UserArrayProxy<T, WIDTH, SIZE>;
private:
void write(size_t i, T x)
{
T& element = data[i / ELEMENTS_PER_T];
int offset = (i % ELEMENTS_PER_T) * WIDTH;
x &= MASK;
element &= ~(MASK << offset);
element |= x << offset;
}
T get(size_t i)
{
return (data[i / ELEMENTS_PER_T] >> ((i % ELEMENTS_PER_T) * WIDTH)) & MASK;
}
T data[NUMBER_OF_TS];
};
int main()
{
typedef UserArray<int, 6, 20> myarray_t;
myarray_t a;
std::cout << "Sizeof a in bytes: " << sizeof(a) << std::endl;
for (size_t i = 0; i != 20; ++i) { a[i] = i; }
for (size_t i = 0; i != 20; ++i) { std::cout << a[i] << std::endl; }
std::cout << "We can even use address_of operator: " << std::endl;
for (myarray_t::ptr_t e = &a[0]; e != &a[20]; ++e) { std::cout << *e << std::endl; }
}