Reputation: 2748
I don't understand why template argument deduction fails in this case:
template<class Iterator> void
f(Iterator x, const Iterator y) {}
int main()
{
const int* cpi;
int* pi;
f(pi,cpi);
}
Why does Iterator
does not deduce to int*
for the second parameter?
What would be the most idiomatic declaration for f
?
Upvotes: 1
Views: 178
Reputation: 117298
You could create a trait to check if the iterator is an iterator over const values.
#include <iterator> // iterator_traits
#include <type_traits> // is_const_v, remove_pointer_t, enable_if_t
template<typename T>
struct is_const_iterator {
// Define a pointer type to the type iterated over. Something already a pointer
// will still be a pointer
using pointer = typename std::iterator_traits<T>::pointer;
// Remove the pointer part from the type and check for constness.
static const bool value = std::is_const_v<std::remove_pointer_t<pointer>>;
};
// Helper variable template to simplify the use of the above.
template<class T>
inline constexpr bool is_const_iterator_v = is_const_iterator<T>::value;
SFINAE use of is_const_iterator_v
template<class It, class CIt, std::enable_if_t<is_const_iterator_v<CIt>, int> = 0>
void f(It x, CIt y) {
//for(; x != y; ++x) std::cout << *x << '\n';
}
Alternatively, if your function doesn't have other overloads (does not need SFINAE), you can use static_assert
to make it even clearer for the user:
template<class It, class CIt>
void f(It x, CIt y) {
static_assert(is_const_iterator_v<CIt>, "Arg 2 must be a const iterator");
//for(; x != y; ++x) std::cout << *x << '\n';
}
Example:
#include <iostream>
#include <vector>
int main() {
int values[]{1, 2};
int* pi = values;
const int* cpi = values + std::size(values);
std::vector<int> v{3, 4};
f(pi, cpi);
f(v.begin(), v.cend());
// f(pi, pi); // error, pi is non-const
// f(v.begin(), v.end()); // error v.end() is non-const
}
Upvotes: 1
Reputation: 310990
The Iterator can be either int *
or const int *
. The qualifier const of the second function parameter means either int * const
or const int * const
.
Upvotes: 1