Search code examples
c++templatesc++20c++-concepts

How to detect a template function should impose a more strict concept


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 vectors. 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.


Solution

  • 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".