#include <cassert>
#include <vector>
using namespace std;
template<typename Type, int Dimension>
const vector<Type> make_fixed_vector(const Type& value = Type())
{
return vector<Type>(Dimension, value);
}
int main(void)
{
vector<int> v3 = make_fixed_vector<int, 3>();
assert(v3.size() == 3);
}
C++1x compilers are able to deduce the type of a variable, which is handy when declaring multi-dimensional "fixed" vectors using this technique:
.
.
.
template<typename Type, int Rows, int Columns>
const vector<vector<Type> > make_fixed_vector_vector(const Type& value = Type())
{
return vector<vector<Type> >(Rows, make_fixed_vector<Type, Columns>(value));
}
int main(void)
{
auto vv = make_fixed_vector_vector<int, 3, 4>(42);
assert(vv.size() == 3);
assert(vv[0].size() == 4);
assert(vv[0][0] == 42);
assert(vv[2][3] == 42);
}
I had this simple idea when programming a parser-function for list expressions which shall return a fixed-size vector of vector of integers. For example, a vector<vector<int> >(1)
for a expression like "(0,8)", but a vector<vector<int> >(2)
for a expression like "(3-4)(5)" and so on. In the application up to 5 parenthesized definitions are possible, which represent logical references to program data. I first try to parse a vector<vector<int> >(5)
. Worked? Ok, got reference type A, the most detailed one. Otherwise vector<vector<int> >(4)
indicates a reference type B etc.
For this purpose make_fixed_vector
worked well, but from a general perspective the technique has flaws. Most notably, since make_fixed_vector
returns no true type, its dimension(s) cannot be checked at compile-time. At runtime reserve
, resize
and push_back
calls are possible. And, since function templates cannot have default template arguments, custom allocators require more typing:
template<typename Type, int Dimension, template<typename> class Allocator>
const vector<Type Allocator<Type> > make_fixed_vector(const Type& value = Type())
{
return vector<Type, Allocator<Type> >(Dimension, value);
}
vector<int> v3 = make_fixed_vector<int, 3, std::allocator>();
etc. etc. But this technique keeps smaller projects basic. Unless this virtue is relevant Boost's boost::array
might be more realistic.