开发者

Understanding on User Defined function

Create a UserArray of bit fields which can be declared as follows: The size occupied by our Array will be less then a normal array. Suppose we want an ARRAY of 20 FLAGs (TRUE/FALSE). A bool FLAG[20] will take 20 bytes of memory, while UserArray<bool,bool,0,20> will take 4 bytes of memory.

  • Use class Template to create user array.
  • Use Bit wise operators to pack the array.
  • Equality operation should also be implemented.

    template<class T开发者_高级运维,int W,int L,int H>//i have used template<class T> 
                                       //but never used such way
    class UserArray{ 
            //....                 
    };        
    typedef UserArray<bool,4,0,20> MyType;
    

where:

  • T = type of an array element
  • W = width of an array element, 0 < W < 8
  • L = low bound of array index (preferably zero)
  • H = high bound of array index

A main program:

int main() {
      MyType Display;  //typedef UserArray<T,W,L,H> MyType; defined above

      Display[0] = FALSE; //need to understand that how can we write this?
      Display[1] = TRUE; //need to understand that how can we write this?

      //assert(Display[0]);//commented once, need to understand above code first
      //assert(Display[1]);//commented once..
      //cout << “Size of the Display” << sizeof(Display);//commented once..
}

My doubt is how those parameters i.e T,L,W & H are used in class UserArray and how can we write instance of UserArray as Display[0] & Display[1] what does it represent?

Short & simple example of similar type will be easy for me to understand.


W, L and H are non-type template parameters. You can instantiate a template (at compile-time) with constant values, e.g.:

template <int N>
class MyArray
{
public:
    float data[N];

    void print() { std::cout << "MyArray of size " << N << std::endl; }
};

MyArray<7> foo;
MyArray<8> bar;

foo.print();  // "MyArray of size 7"
bar.print();  // "MyArray of size 8"

In the example above, everywhere that N appears in the template definition, it will be replaced at compile-time by the supplied constant.

Note that MyArray<7> and MyArray<8> are completely different types as far as the compile is concerned.

I have no idea what the solution to your specific problem is. But your code won't compile, currently, as you have not provided values for the template parameters.


This is not simple, particularly as you can have variable bit widths.

<limits.h> has a constant CHAR_BIT, which is the number of bits in a byte. Usually this is 8, but it could be greater than 8 (not less though).

I suggest the number of elements per byte be CHAR_BIT / W. This might waste a few bits for example, if width is 3 and CHAR_BIT is 8, but this is complicated enough as is.

You'll then need to define operator[] to access the elements, and likely need to do some bit fiddling to do this. For the non-const version of operator[], you'll probably have to return some sort of proxy object when there are more than one elements in a byte, and have its operator= overridden so it writes back to the appropriate spot in the array.

It's a good exercise though to figure this one out though.


Here's some code that implements what you ask for, except the lower bound is fixed at 0. It also shows a rare use case for the address_of operator. You could take this further and make this container compatible with STL algorithms if you liked.

#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; }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜