I am creating a custom Vector/ArrayList class. But i´m having troubles creating the iterative version of the constructor. The following code works, but the problem is when i
Note that some compilers start supporting the new features of C++20, including concepts: https://en.cppreference.com/w/cpp/compiler_support
So to differentiate between your two constructors, with C++20 you restrict the allowed template arguments using a concept type:
template<std::random_access_iterator ITER>
// see comment by Nathan Oliver for using random_access_iterator
ArrayList(ITER begin, ITER end)
: arr_size{ static_cast<size_type>(end - begin) }, arr_capacity{ arr_size }
{
std::uninitialized_copy(begin, end, array = allocator.allocate(arr_size));
first = array;
last = array + arr_size - 1;
}
If you wish to define your own concept (no need to in this case, just for the sake of the exercise), you can define a concept for an Iterator:
template<typename ITER>
concept Iterator = requires {
typename std::iterator_traits<ITER>::iterator_category;
};
Or, for the use in this case, a RandomAccessIterator:
template<typename ITER>
concept RandomAccessIterator = std::is_base_of_v <
std::random_access_iterator_tag,
typename std::iterator_traits<ITER>::iterator_category
>;
And use it the same as above, for example:
template<RandomAccessIterator ITER>
ArrayList(ITER begin, ITER end) // ...
Code: https://godbolt.org/z/gBevvC
(Note that RandomAccessIterator should be part of ranges, but can be implemented on your own as above).
What you need to do is use SFINAE to constrain the template to only work when the template type is deduced to be an iterator type. Since you do arr_size{ static_cast<size_type>(end - begin) }
to initialize size
this means that you expect the iterators to be random access. We can check for that using the iterator_category
of std::iterator_traits Doing that gives you
template<typename ITER,
std::enable_if_t<std::is_base_of_v<typename std::iterator_traits<ITER>::iterator_category,
std::random_access_iterator_tag>, bool> = true>
ArrayList(ITER begin, ITER end) : arr_size{ static_cast<size_type>(end - begin) }, arr_capacity{ arr_size }
{
std::uninitialized_copy(begin, end, array = allocator.allocate(arr_size));
first = array;
last = array + arr_size - 1;
}