了解用户定义的功能

时间:2011-07-14 10:11:42

标签: c++ templates user-defined-functions

创建一个可以声明如下的位字段UserArray:我们的Array占用的大小将小于普通数组。假设我们想要一个20个FLAG的ARRAY(TRUE / FALSE)。 bool FLAG[20]将占用20个字节的内存,而UserArray<bool,bool,0,20>将占用4个字节的内存。

  • 使用类模板创建用户数组。
  • 使用逐位运算符打包数组。
  • 还应实施平等运作。

    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 < W&lt; 8
  • 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]&amp; Display[1]它代表什么?

短&amp;类似类型的简单示例很容易让我理解。

3 个答案:

答案 0 :(得分:2)

WLH非类型模板参数。您可以使用常量值(例如:

)实例化模板(在编译时)
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 :(得分:1)

这并不简单,特别是因为您可以使用可变位宽。

<limits.h>有一个常量CHAR_BIT,它是一个字节中的位数。通常这是8,但它可能大于8(不小于)。

我建议每个字节的元素数量为CHAR_BIT / W。例如,如果宽度为3CHAR_BIT8,则可能会浪费一些比特,但这很复杂。

然后,您需要定义operator[]来访问元素,并且可能需要做一些小小的操作才能执行此操作。对于非{const}版本的operator[],当一个字节中有多个元素时,你可能不得不返回某种代理对象,并且它的operator=被覆盖,所以它会写回数组中的适当位置。

尽管如此,这是一个很好的练习。

答案 2 :(得分:1)

这是一些实现你要求的代码,除了下限固定为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; }
}