Понимание пользовательской функции - PullRequest
0 голосов
/ 14 июля 2011

Создайте пользовательский массив битовых полей, который можно объявить следующим образом: размер, занимаемый нашим массивом, будет меньше, чем у обычного массива. Предположим, нам нужен массив из 20 флагов (ИСТИНА / ЛОЖЬ). bool FLAG[20] займет 20 байтов памяти, а UserArray<bool,bool,0,20> - 4 байта памяти.

  • Используйте класс Template для создания пользовательского массива.
  • Используйте битовые операторы для упаковки массива.
  • Операция равенства также должна быть реализована.

    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;
    

где:

  • T = тип элемента массива
  • W = ширина элемента массива, 0
  • L = нижняя граница индекса массива (предпочтительно ноль)
  • H = верхняя граница индекса массива

Основная программа:

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..
}

Я сомневаюсь, как эти параметры, то есть T,L,W & H используются в классе UserArray, и как мы можем записать экземпляр UserArray как Display[0] & Display[1], что он представляет?

Мне будет легко понять короткий и простой пример подобного типа.

Ответы [ 3 ]

2 голосов
/ 14 июля 2011

W, L и H являются нетиповыми параметрами шаблона . Вы можете создать экземпляр шаблона (во время компиляции) с постоянными значениями, например ::10000

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"

В приведенном выше примере везде, где N присутствует в определении шаблона, оно будет заменено в время компиляции на предоставленную константу.

Обратите внимание, что MyArray<7> и MyArray<8> - это совершенно разные типы для компиляции.

Понятия не имею, каково решение вашей конкретной проблемы. Но в настоящее время ваш код не будет компилироваться, поскольку вы не указали значения параметров шаблона.

1 голос
/ 14 июля 2011

Вот некоторый код, который реализует то, что вы запрашиваете, за исключением того, что нижняя граница зафиксирована на 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; }
}
1 голос
/ 14 июля 2011

Это не просто, особенно потому, что вы можете иметь переменную ширину битов.

<limits.h> имеет константу CHAR_BIT, которая является количеством битов в байте.Обычно это 8, но это может быть больше 8 (но не меньше).

Я предлагаю количество элементов в байте CHAR_BIT / W.Например, это может привести к потере нескольких битов, если ширина равна 3, а CHAR_BIT равна 8, но это достаточно сложно, как есть.

Затем вам потребуется определить operator[] для доступаэлементы, и, вероятно, нужно сделать немного возиться, чтобы сделать это.Для неконстантной версии operator[] вам, вероятно, придется возвращать какой-то прокси-объект, когда в байте более одного элемента, и он переопределен operator=, поэтому он записывает обратно в соответствующее место в байте.массив.

Хотя это хорошее упражнение, чтобы понять это.

...