In C++, I am making an implementation of the vector
class and came across an error when using any type as the argument for T
:
void insert(iterator where, size_type count, const_reference value = T()){...}
template <typename InIt>
void insert(iterator where, InIt first, InIt last){...}
When doing the following:
vector<int> v;
for (int i = 0; i < 5; ++i)
{
v.push_back(i + 1);
}
v.insert(v.begin() + 2, 10, 8);
v.insert(v.begin() + 4, 9);
It takes the argument for InIt
as int
, when it should in fact be an iterator
type class and means that the wrong function is called, resulting in internal memory errors. As a result, I have had to remove the insert
function with the template <typename InIt>
argument as it ruins my implementation. I have tried this with std::string
and the same problem occurs.
Is there anything I can do to differentiate these two functions?
This is what SFINAE is for - remove the 2nd overload from the overload set if InIt
is not something that looks like an iterator. In this case, you just want an input iterator, which has to be both incrementable and dereferencable:
template <typename InIt,
typename = decltype(*std::declval<InIt&>(),
++std::declval<InIt&>())>
void insert(iterator where, InIt first, InIt last)
{
...
}
If you were to call insert
with some integral type (so that it can be converted to size_t
), *std::declval<InIt&>
would be an invalid expression since integral types aren't dereferencable - so template deduction would fail. Because Substitution Failure Is Not An Error, the effect is that this overload is removed from consideration, and the first one would be called instead.