1 // -*-c++-*- 2 /* $Id$ */ 3 4 /* 5 * 6 * Copyright (C) 1998 David Mazieres (dm@uun.org) 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2, or (at 11 * your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 21 * USA 22 * 23 */ 24 25 /* ***** WHY: 26 * 27 * C arrays (e.g. "int c[64];") vastly complicate some aspects of C++ 28 * template programming. Suppose you have a template tmpl with a 29 * class parameter T, and T is instantiated with an array: 30 * 31 * class elm { 32 * //... 33 * }; 34 * 35 * template<class T> tmpl { 36 * //... 37 * }; 38 * 39 * typedef tmpl<elm[64]> problem_t; 40 * 41 * If, for instance, tmpl generally needs to allocate an object of 42 * type T, a function in tmpl might have code like this: 43 * 44 * T *objp = new T; 45 * 46 * However, this won't work when T is elm[64], because the code 47 * "new elm[64]" returns an "elm *", not a "(*) elm[64]". 48 * 49 * Worse yet, any code that uses placement new or calls destructors 50 * will not work. If T is an array, then allocating a "new T" invokes 51 * operator new[] rather than operator new, and that generally 52 * requires more than sizeof(T) bytes. 53 * 54 * Finally, a lot of template classes require things like copy 55 * constructors or assignment to work, and neither of those does with 56 * C arrays. 57 * 58 * 59 * ***** WHAT: 60 * 61 * The simple solution to all these problems is simply not to use C 62 * arrays. The dirt-simple type "array<type, size>" is simply an 63 * array wrapped in a structure. These arrays can be allocated with 64 * the ordinary scalar new, and things like assignment and copy 65 * construction will work fine. 66 * 67 * The macro "toarray" converts a C array type to a template array. 68 */ 69 70 #ifndef _ARRAY_H_WITH_TOARRAY_ 71 #define _ARRAY_H_WITH_TOARRAY_ 1 72 73 #include <stddef.h> 74 75 template<class T, size_t n> struct array; 76 77 template<class T> struct __toarray { 78 typedef T type; 79 }; 80 template<class T, size_t n> struct __toarray<T[n]> { 81 typedef array<typename __toarray<T>::type, n> type; 82 }; 83 #define toarray(T) __toarray<T>::type 84 85 template<class T, size_t n> class array { 86 public: 87 typedef typename toarray(T) elm_t; 88 enum { nelm = n }; 89 90 private: 91 elm_t a[nelm]; 92 93 #ifdef CHECK_BOUNDS 94 void bcheck (size_t i) const { assert (i < nelm); } 95 #else /* !CHECK_BOUNDS */ 96 void bcheck (size_t) const {} 97 #endif /* !CHECK_BOUNDS */ 98 99 public: 100 static size_t size () { return nelm; } 101 102 elm_t *base () { return a; } 103 const elm_t *base () const { return a; } 104 105 elm_t *lim () { return a + nelm; } 106 const elm_t *lim () const { return a + nelm; } 107 108 elm_t &operator[] (ptrdiff_t i) { bcheck (i); return a[i]; } 109 const elm_t &operator[] (ptrdiff_t i) const { bcheck (i); return a[i]; } 110 }; 111 112 #endif /* _ARRAY_H_WITH_TOARRAY_ */ 113