So, I have different behaviour for range and non-range versions of less
functor. That’s a minimal code example to reproduce the behaviour:
#include <vector>
#include <algorithm>
#include <functional>
class Int
{
public:
Int(int d) : m_data(d) {}
auto operator<=>(const Int& other) const {
return this->m_data <=> other.m_data;
}
private:
int m_data;
};
int main()
{
Int x(15);
Int y(17);
std::invoke(std::less(), x, y); // OK, compiles well
std::invoke(std::ranges::less(), x, y); // ERROR, does not compile
}
If you replace Int
class with a primitive type like int
, everything will be fine and will work as expected.
I’ve got a comiler error at the std::invoke(std::ranges::less(), x, y);
line.
Error for Microsoft Visual Studio 2022 17.9.6
Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept(<expr>)'
C:UsersC-401Desktoptestheap_testheap_test.cpp(24,9):
With the following template arguments:
C:UsersC-401Desktoptestheap_testheap_test.cpp(24,9):
'_Callable=std::ranges::less'
C:UsersC-401Desktoptestheap_testheap_test.cpp(24,9):
'_Ty1=Int &'
C:UsersC-401Desktoptestheap_testheap_test.cpp(24,9):
'_Types2={Int &}'
C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.39.33519includetype_traits(1736,50):
'std::_Invoker_functor::_Call': no matching overloaded function found
C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.39.33519includetype_traits(1633,27):
could be 'unknown-type std::_Invoker_functor::_Call(_Callable &&,_Types &&...) noexcept(<expr>)'
C:Program FilesMicrosoft Visual Studio2022CommunityVCToolsMSVC14.39.33519includetype_traits(1727,19):
or 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)'
C:UsersC-401Desktoptestheap_testheap_test.cpp(24,9):
'unknown-type std::invoke(_Callable &&) noexcept(<expr>)': expects 1 arguments - 3 provided
Error for gcc (looked via cppinsights . io service)
/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/functional:110:5: note: candidate template ignored: substitution failure [with _Callable = std::ranges::less, _Args = <Int &, Int &>]: no type named 'type' in 'std::invoke_result<std::ranges::less, Int &, Int &>'
110 | invoke(_Callable&& __fn, _Args&&... __args)
| ^
Some background info
Originally I faced that problem when I noticed that I am not able to use std::ranges::make_heap()
, std::ranges::push_heap()
and std::ranges::pop_heap()
for my std::vector<T>
where T
type is quite like the Int
in the code above – it contains several members and type should be comparable only by of these members, so I have the same operator<=>
there. I’ve dug deep the template errors I’ve got and discovered that originally error is caused by the less
function, but now I’m kinda stuck to explain the cause of the error
1