how-to initialize 'const std::vector<T>' like a c array
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 };
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:
- you can't, because the function might alter the vector and your object/reference is const. Make a non-const copy of the original, and pass that in.
or
- use
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 *
]
Short and dirty way (similar to Boost's list_of()
)
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T>
struct vlist_of : public vector<T> {
vlist_of(const T& t) {
(*this)(t);
}
vlist_of& operator()(const T& t) {
this->push_back(t);
return *this;
}
};
int main() {
const vector<int> v = vlist_of<int>(1)(2)(3)(4)(5);
copy(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"));
}
Now, C++11 has initializer lists, so you don't need to do it that way or even use Boost. But, as an example, you can do the above in C++11 more efficiently like this:
#include <iostream>
#include <vector>
#include <utility>
#include <ostream>
using namespace std;
template <typename T>
struct vlist_of : public vector<T> {
vlist_of(T&& t) {
(*this)(move(t));
}
vlist_of& operator()(T&& t) {
this->push_back(move(t));
return *this;
}
};
int main() {
const vector<int> v = vlist_of<int>(1)(2)(3)(4)(5);
for (const auto& i: v) {
cout << i << endl;
}
}
But, it's still not as efficient as using a C++11 initializer list because there's no operator=(vlist_of&&)
defined for vector.
tjohns20's way modified like the following might be a better c++11 vlist_of
:
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
template <typename T>
class vlist_of {
public:
vlist_of(T&& r) {
(*this)(move(r));
}
vlist_of& operator()(T&& r) {
v.push_back(move(r));
return *this;
}
vector<T>&& operator()() {
return move(v);
}
private:
vector<T> v;
};
int main() {
const auto v = vlist_of<int>(1)(2)(3)(4)(5)();
for (const auto& i : v) {
cout << i << endl;
}
}