Is there an elegant way to create and initialize a const std::vector
like const T a[] = { ... }
to a fixed (and small) number of val
If you're asking how to initialise a const vector so that it has interesting contents, then the answer is probably to use the copy constructor. First you laboriously fill in a vector, then you create your new const vector from it. Or you can use the vector<InputIterator>(InputIterator, InputIterator)
constructor template to initialise from some other kind of container or an array. If an array, then that could have been defined with an initialisation list.
Something like this is hopefully close to what you want:
const T ra[3] = {t1, t2, t3};
const vector<const T> v(ra, ra+3);
If you're asking how to pass a const vector into a function which takes a vector then the answer is either:
or
const_cast
to remove the constness in order to pass it into a function which takes a non-const vector but which you just so happen to know will not modify the vector.The latter is one of those things which will, quite rightly, cause anyone who sees it to make comments about goggles, and the fact that they do nothing. It's exactly what const_cast
is for, but there's a reasonably strong argument that says if you need const_cast
, you have already lost.
Doing both of those things (creating a const vector from a non-const one with the copy constructor, and then casting away constness) is definitely wrong - you should have just used a non-const vector. So pick at most one of these to do...
[Edit: just noticed that you're talking about a difference between vector<T>
and const vector<const T>
. Unfortunately in the STL, vector<const T>
and vector<T>
are completely unrelated types, and the only way to convert between them is by copying. This is a difference between vectors and arrays - a T**
can be silently and safely converted to const T *const *
]
If they're all the same you can just do
vector<T> vec(num_items, item);
but I assume they're not - in which case the neatest way is probably:
vector<T> vec(num_items);
vec[0] = 15;
vec[1] = 5;
...
C++0x will let you use an initialiser list in exactly the way you're thinking of, but that's not a lot of good right now, unfortunately.
You either have to wait for C++0x or use something like Boost.Assign to do that.
e.g.:
#include <boost/assign/std/vector.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope
vector<int> v;
v += 1,2,3,4,5;
for C++11:
vector<int> luggage_combo = { 1, 2, 3, 4, 5 };
Based on Shadow2531's response, I'm using this class to initialise vectors, without actually inheriting from std::vector like Shadow's solution did
template <typename T>
class vector_init
{
public:
vector_init(const T& val)
{
vec.push_back(val);
}
inline vector_init& operator()(T val)
{
vec.push_back(val);
return *this;
}
inline std::vector<T> end()
{
return vec;
}
private:
std::vector<T> vec;
};
Usage:
std::vector<int> testVec = vector_init<int>(1)(2)(3)(4)(5).end();
Compared to Steve Jessop's solution it creates a lot more code, but if the array creation isn't performance critical I find it a nice way to initialise an array in a single line
Not sure if I understood you right. I understand your question like this: you want to initialize a vector to a large number of elements. What's wrong with using push_back()
on the vector? :-)
If you know the number of elements to be stored (or are sure that it will store less than the next power of 2) you can do this, if you have a vector of pointers of type X (works only with pointers):
std::vector< X* > v;
v.reserve(num_elems);
X* p = v.begin();
for (int count = 0; count < num_elems; count++)
p[count] = some_source[count];
Beware of adding more than the next power of 2 elements, even if using push_back()
. Pointers to v.begin()
will then be invalid.
How about:
int ar[]={1,2,3,4,5,6};
const int TotalItems = sizeof(ar)/sizeof(ar[0]);
std::vector<int> v(ar, ar+TotalItems);