Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Less than operator through implicit conversion?

Consider the following class:

struct C 
{
     /* Class contents, without any arithmetic operator... */
     constexpr operator int() noexcept; // Implicit conversion to int
};

My question is:

  • Is C usable in standard algorithms like std::sort that currently uses the default < operator?
  • Is C considered as satisfying the LessThanComparable concept?
  • Will C meet the requirements of an hypothetical conceptified algorithm library that would require the type to be LessThanComparable.
like image 503
Vincent Avatar asked Dec 29 '15 09:12

Vincent


1 Answers

Is C usable in standard algorithms like std::sort that currently uses the default < operator?

Yes, it works for std::sort() and some other standard algorithms. The code

#include <algorithm>
#include <vector>

struct C 
{
     /* Class contents, without any arithmetic operator... */
     constexpr operator int() noexcept {return 0;} // Implicit conversion to int
};

int main()
{
    std::vector<C> v;  
    std::sort( begin(v), end(v) );
}

compiles. Here's a live demo. Look at the next question though!

Is C considered as satisfying the LessThanComparable concept?

No. The requirements of the LessThanComparable concept are, that for objects x and y of type C or const C the expression x<y is valid and implicitly convertible to bool and the < operator establishes a strict weak ordering relation. In your case const objects do will not convert to ints. This is a bug in your code, because it is not const correct. Adding the const keyword will make it work and the class C would indeed be LessThanComparable. The strict weak ordering relation is fulfilled, because ints fulfil this requirement.

Will C meet the requirements of an hypothetical conceptified algorithm library that would require the type to be LessThanComparable.

If you fix your constness, yes, it will.

A few sidenotes:

  • GCC 4.9 compiles x<y even if x and y are of type const C. This seems to be a compiler bug, since GCC 5.2 and clang 3.6 throw a compile time error here.

  • Passing std::less<C>() as an extra argument to std::sort() gives a compile time error, because the compare function requires constant objects to be comparable in that case. However, passing std::less<void>() doesn't break anything, since arguments are perfectly forwarded.

  • The std::sort() algorithm does not require a full LessThanComparable, but the concept Compare. Furthermore, the iterator type must be a RandomAccessIterator that is ValueSwappable and the dereferenced type must be MoveContructable and MoveAssignable. This is all the case for your first question, even when the constness bug is not fixed. That's why std::sort() and other standard algorithms work.

like image 155
Ralph Tandetzky Avatar answered Oct 21 '22 18:10

Ralph Tandetzky