I have some code that looks like this:
#include <iterator>
#include <list>
#include <vector>
template<std::forward_iterator Iter>
auto less(Iter i1, Iter i2)
{
return i1 < i2;
}
int main()
{
auto vec = std::vector<int>();
auto list = std::list<int>();
(void) less(vec.begin(), vec.end());
//(void) less(list.begin(), list.end()); // error: no match for 'operator<'
}
Basically, the less
template function states Iter
template parameter has to meet requirements of forward iterator, while the implementation uses operator<
, which is provided by random access iterator.
The code works by accident, because it only uses vector
s. Is there a compiler warning, static analysis tool, or anything else that could help detect function that requires a more strict concept than it states?
I realise this could be detected with a unit test, but it would be nice to have a tool to guide the testing/fixing effort in a large code base.
I think the best thing to do here is a style change to requires statements for everything that is required of the type instead of assuming there is always going to be an std concept that matches. That way you can look at the code and know it will work. So your code would be
template<typename Iter>
requires(
requires(Iter a, Iter b){a < b;}
)
auto less(Iter i1, Iter i2)
{
return i1 < i2;
}
It is a little more verbose but it makes it very clear what you want to do here and there is no room for things to "work by accident".