Reputation: 60381
I've made a container class in C++, and I have a constructor from iterators so I can write MyContainer<double> x(v.begin(), v.end())
where v
is a std::vector<double>
. I would like to be able to do the same with a c-array but :
double array[3] = {1., 2. , 3.};
MyContainer<double> x(array, array+3); // Doesn't work : no matching function for call to ‘MyContainer<double>::MyContainer(double [3], double*)’
MyContainer<double> x(array+0, array+3); // Work
What is the origin of the problem and how to solve it ?
Thank you very much.
Upvotes: 2
Views: 165
Reputation: 137810
Don't accept references to iterators, take them by value. It's trying to pass a reference to an array; the failing expression needs the array to decay to a pointer.
Presumably you have
template< typename Iter >
MyContainer( Iter const &first, Iter const &last );
but you need
template< typename Iter >
MyContainer( Iter first, Iter last );
Iterators need to be lightweight enough to pass by value; all the standard templates do so.
An array cannot be used as an iterator because it cannot be incremented. The storage is fixed. When you use an array in an expression like arr + 0
or pass it by value to a function, it is implicitly converted to a pointer to its first element. But that conversion doesn't happen when passing by reference.
Upvotes: 4
Reputation: 726559
The result of array+0
is a pointer, while array
itself is not a pointer, it is an array. Your constructor does not have an overload that takes an array and a pointer, hence the compile fails.
The idiomatic way of dealing with the problem of making the beginning and the ending iterators from an array is using the begin(...)
and end(...)
functions:
MyContainer<double> x(std::begin(array), std::end(array));
The overload takes care of figuring out where the end of your array is, freeing you from the need to add array's length to the pointer.
Upvotes: 3