File: fixedvector.h

package info (click to toggle)
crawl 2%3A0.33.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 95,264 kB
  • sloc: cpp: 358,145; ansic: 27,203; javascript: 9,491; python: 8,359; perl: 3,327; java: 2,667; xml: 2,191; makefile: 1,830; sh: 611; objc: 250; cs: 15; sed: 9; lisp: 3
file content (126 lines) | stat: -rw-r--r-- 3,206 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * @file
 * @brief Fixed size vector class that asserts if you do something bad.
**/

#pragma once

#include <algorithm>
#include <cstdarg>
#include <cstring>
#include <vector>

#include "debug.h"

using std::vector;

// TODO: this class precedes std::array and is quite redundant with it, except
// for the bounds check in operator[] (which std::array only has on `at`).
// Should we replace / subclass / use as an underlying implementation?

template <class TYPE, int SIZE> class FixedVector
{

public:
    typedef TYPE            value_type;
    typedef TYPE&           reference;
    typedef const TYPE&     const_reference;
    typedef TYPE*           pointer;
    typedef const TYPE*     const_pointer;

    typedef unsigned long   size_type;
    typedef long            difference_type;

    typedef TYPE*           iterator;
    typedef const TYPE*     const_iterator;

public:
    ~FixedVector()                           {}

    FixedVector()                            {}

    FixedVector(TYPE def) : mData()
    {
        init(def);
    }

    FixedVector(TYPE value0, TYPE value1, ...);
    // Allows for something resembling C array initialization, eg
    // instead of "int a[3] = {0, 1, 2}" you'd use "FixedVector<int, 3>
    // a(0, 1, 2)". Note that there must be SIZE arguments.

public:
    // ----- Size -----
    bool empty() const { return SIZE == 0; }
    size_t size() const { return SIZE; }

    // ----- Access -----
    // why don't these use size_t??
    // these are more like std::array::at than std::array::operator[]
    TYPE& operator[](unsigned long index)
    {
#ifdef ASSERTS
        if (index >= SIZE)
        {
            // Intentionally printed as signed, it's very, very unlikely we'd
            // have a genuine big number here, but underflows are common.
            die_noline("range check error (%ld / %d)", (signed long)index,
                SIZE);
        }
#endif
        return mData[index];
    }

    const TYPE& operator[](unsigned long index) const
    {
#ifdef ASSERTS
        if (index >= SIZE)
        {
            die_noline("range check error (%ld / %d)", (signed long)index,
                SIZE);
        }
#endif
        return mData[index];
    }

    const TYPE* buffer() const { return mData; }
    TYPE* buffer() { return mData; }

    // ----- Iterating -----
    iterator begin() { return mData; }
    const_iterator begin() const { return mData; }

    iterator end() { return begin() + size(); }
    const_iterator end() const { return begin() + size(); }
    void init(const TYPE& def);

    // std::array api
    void fill(const TYPE& def) { init(def); }

protected:
    TYPE    mData[SIZE];
};

template <class TYPE, int SIZE>
FixedVector<TYPE, SIZE>::FixedVector(TYPE value0, TYPE value1, ...)
{
    mData[0] = value0;
    mData[1] = value1;

    va_list ap;
    va_start(ap, value1);   // second argument is last fixed parameter

    for (int index = 2; index < SIZE; index++)
    {
        TYPE value = va_arg(ap, TYPE);
        mData[index] = value;
    }

    va_end(ap);
}

template <class TYPE, int SIZE>
void FixedVector<TYPE, SIZE>::init(const TYPE& def)
{
    std::fill(std::begin(mData), std::end(mData), def);
}