问题
I am implementing a container in c++, a wrapper for an array in fact. I am not sure how to implement a constructor from initializer_list. I end up with this implementation but it seems to me really ugly. So could be an array allocated in a heap initialized by an initializer_list. Or is there an elegant way how to do it?
template <typename T> class sequence {
public:
sequence (size_t n): _data {new T[n]}, _size {n} {};
sequence (std::initializer_list<T> source);
~sequence() { delete[] _data; };
private:
pointer _data;
size_type _size;
};
//Initializer list constructor
template <class T> sequence<T>::sequence (std::initializer_list<T> source)
: sequence(source.size()) {
auto iterator = source.begin();
for ( int i=0; i < _size; i++) {
_data[i] = *iterator;
++iterator;
}
};
回答1:
Depends on what you're trying to do.
If you're actually needing to use a sequence with bounded size, as determined at compile-time, then use std::array<T,std::size_t>
, which is a wrapper around a C-style array (like what you are implementing), introduced in C++11.
However, as you said in one of your comments, you're doing this mostly for educational purposes. In that case, what you have is decent. The syntax could be cleaned up a little. Consider:
//Initializer list constructor
template <class T>
sequence<T>::sequence (std::initializer_list<T> source)
: sequence(source.size())
{
auto it = source.begin();
auto const e = source.cend();
auto d = data_;
while (it != e) {
*d++ = *it++;
}
};
That way you don't explicitly rely on the size()
. You could consider making things more efficient by turning the it
and e
iterators into "move" iterators:
auto it = std::make_move_iterator(source.begin());
auto e = std::make_move_iterator(source.end());
That way, whenever it's dereferenced, its value is cast to an rvalue reference, allowing a move assignment.
来源:https://stackoverflow.com/questions/37682360/constructor-from-initializer-list