I am using the following template function in order to copy the first n elements from one vector to another.
// Example program
#include <iostream>
#include <string>
#include <vector>
template <typename Range>
inline std::vector<typename Range::value_type> take(const Range &iRange, int nbrElements) {
std::vector<typename Range::value_type> result;
if (nbrElements > iRange.size()) {
nbrElements = iRange.size();
}
std::copy_n(iRange, nbrElements, std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> source = { 1, 2, 3, 4, 5, 6, 7,};
std::vector<int> destination = take(source, 7);
return 0;
}
The problem is that I am getting the following error and I don't understand why:
In instantiation of 'std::vector<typename Range::value_type>
take(const Range&, int) [with Range = std::vector<int>; typename
Range::value_type = int]':
22:48: required from here
10:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
In file included from /usr/include/c++/4.9/algorithm:62:0,
from 5:
/usr/include/c++/4.9/bits/stl_algo.h: In instantiation of '_OIter std::copy_n(_IIter, _Size, _OIter) [with _IIter = std::vector<int>;
_Size = int; _OIter = std::back_insert_iterator<std::vector<int> >]':
14:62: required from 'std::vector<typename Range::value_type> take(const Range&, int) [with Range = std::vector<int>; typename
Range::value_type = int]'
22:48: required from here
/usr/include/c++/4.9/bits/stl_algo.h:804:39: error: no matching function for call to '__iterator_category(std::vector<int>&)'
std::__iterator_category(__first));
^
/usr/include/c++/4.9/bits/stl_algo.h:804:39: note: candidate is:
In file included from /usr/include/c++/4.9/bits/stl_algobase.h:65:0,
from /usr/include/c++/4.9/bits/char_traits.h:39,
from /usr/include/c++/4.9/ios:40,
from /usr/include/c++/4.9/ostream:38,
from /usr/include/c++/4.9/iostream:39,
from 2:
/usr/include/c++/4.9/bits/stl_iterator_base_types.h:201:5: note: template<class _Iter> typename
std::iterator_traits<_Iterator>::iterator_category
std::__iterator_category(const _Iter&)
__iterator_category(const _Iter&)
^
/usr/include/c++/4.9/bits/stl_iterator_base_types.h:201:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.9/bits/stl_iterator_base_types.h: In substitution of 'template<class _Iter> typename
std::iterator_traits<_Iterator>::iterator_category
std::__iterator_category(const _Iter&) [with _Iter =
std::vector<int>]':
/usr/include/c++/4.9/bits/stl_algo.h:804:39: required from '_OIter std::copy_n(_IIter, _Size, _OIter) [with _IIter =
std::vector<int>; _Size = int; _OIter =
std::back_insert_iterator<std::vector<int> >]'
14:62: required from 'std::vector<typename Range::value_type> take(const Range&, int) [with Range = std::vector<int>; typename
Range::value_type = int]'
22:48: required from here
/usr/include/c++/4.9/bits/stl_iterator_base_types.h:201:5: error: no type named 'iterator_category' in 'struct
std::iterator_traits<std::vector<int> >'
There are two issues with the code. The first is that it needs to have #include <algorithm>
, which defines std::copy_n
, and the second is that you need to take the begin()
of range.
When fixed, this is what the code looks like:
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
template <typename Range>
inline std::vector<typename Range::value_type> take(const Range &iRange, int nbrElements) {
std::vector<typename Range::value_type> result;
if (nbrElements > iRange.size()) {
nbrElements = iRange.size();
}
std::copy_n(iRange.begin(), nbrElements, std::back_inserter(result));
return result;
}
int main()
{
std::vector<int> source = { 1, 2, 3, 4, 5, 6, 7,};
std::vector<int> destination = take(source, 7);
return 0;
}
We can take advantage of std::vector
's range constructor to write a shorter, very efficient version of take
by using std::vector
's range constructor:
template <class Range, class value_t = typename Range::value_type>
std::vector<value_t> take(const Range &range, size_t count) {
// Ensure count is at most range.size()
count = std::min(count, range.size());
return std::vector<value_t>(range.begin(), range.begin() + count);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With