Unexpected result of std::is_invocable over a template type
I think it's very important to look at what std::is_invocable
does:
Determines whether
Fn
can be invoked with the argumentsArgTypes...
. Formally, determines whetherINVOKE(declval<Fn>(), declval<ArgTypes>()...)
is well formed when treated as an unevaluated operand, whereINVOKE
is the operation defined inCallable
.
Emphasis mine.
The important part to note here is that std::equal_to<>
used inside std::is_invocable
will never be evaluated because it's a unevaluated operand. This means that it only checks if operator==
exists at all, which it does for std::vector<>
, not if it would compile in an evaluated context.
I think, this is correct behavior.
In the first std::is_invokable_v
checks for the presence of the operator==
in the TNonComparable
type. It is not present - so the result is 0.
In the second case std::is_invokable_v
checks for the equality operator of the std::vector
, which is present and may be invoked. But if do try to invoke it, it won't be able to compile because the TNonComparable
type doesn't have operator==
. But before you don't try to use it, it won't generate an error.
Maybe, in second case you should check for value_type of the std::vector:
std::cout << std::is_invocable_v<
std::equal_to<>,
std::vector<TNonComparable>::value_type,
std::vector<TNonComparable>::value_type
> << "\n";
// 0