3

https://godbolt.org/z/P97MaK

I'm playing with concepts and expected std::is_equality_comparable to work for vector but it does not.

#include <type_traits>
#include <vector>
#include <concepts>


struct X {};

template<std::equality_comparable T>
bool foo( T v){
    return v == v;
}

int main()
{
    foo(10);
    foo(std::vector<X>{});
    
}

the compile error fails inside foo rather than at the function boundary protected by the concept.

enter image description here

Is this a bug or expected behaviour?

bolov
  • 72,283
  • 15
  • 145
  • 224
bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217
  • 2
    because `X` is not equality_comparable – bolov Mar 12 '21 at 11:09
  • Sorry if I'm not clear. I know X is not equality comparable. However this also means that std::vector is not equality comparable. I would expect it to fail there rather than inside the implementation of vector. – bradgonesurfing Mar 12 '21 at 11:11
  • vector comparison operators are not SFINAE friendly, i.e. they are unconditionally defined, making `vector` satisfying `equality_comparable` concept, even though you can't compare them. – bolov Mar 12 '21 at 11:12
  • The general question is what is the intended behaviour is std::is_equality_comparable for templated types. Is it intended to return true if it *might* be equality comparable. – bradgonesurfing Mar 12 '21 at 11:12
  • 4
    For it to fail the vector's operators must be declared SFINAE friendly. That isn't currently required. – StoryTeller - Unslander Monica Mar 12 '21 at 11:13
  • @StoryTeller-UnslanderMonica Is there an open request to make the operators in vector SFINAE friendly. It certainly is unexpected behaviour. – bradgonesurfing Mar 12 '21 at 11:14
  • 1
    I haven't seen one yet. But I don't follow closely for a good while now. It would certainly make a lot of sense to conceptify the standard library's operator templates. – StoryTeller - Unslander Monica Mar 12 '21 at 11:17

1 Answers1

5

A concepts only checks that the declaration is well formed, it doesn't check the definition.

The comparison operators for std::vector are not SFINAE friendly, i.e. they are unconditionally declared, meaning that operator==(vector<T>, vector<T>) always exists, even if operator==(T, T) doesn't exists. That's why equality_comparable<std::vector<T>> is always satisfied and you get an error on v == v inside the function.

For it to work properly the vector comparison operators should be constrained, i.e.:

template< class T, class Alloc >
    requires std::equality_comparable<T>
constexpr ret_type operator==( const std::vector<T,Alloc>& lhs,
                                       const std::vector<T,Alloc>& rhs );
bolov
  • 72,283
  • 15
  • 145
  • 224
  • For this to be fixed in the std::library does this require a change to the standard specification or is it undefined as to whether each vendor gcc/clang/msvc should/will fix it? – bradgonesurfing Mar 12 '21 at 11:58
  • 1
    @bradgon the standard. Note I write a custom trait that deals with this common case by testing the tyoe T instead of vector of T and falls back on the normal trait. – Yakk - Adam Nevraumont Mar 12 '21 at 14:06