Рассмотрим следующий класс:
struct C
{
/* Class contents, without any arithmetic operator... */
constexpr operator int() noexcept; // Implicit conversion to int
};
Мой вопрос:
std::sort
который в настоящее время использует по умолчанию < оператор?LessThanComparable
концепция?LessThanComparable
,Является
C
можно использовать в стандартных алгоритмах, таких какstd::sort
который в настоящее время использует
по умолчанию<
оператор?
Да, это работает для std::sort()
и некоторые другие стандартные алгоритмы. Код
#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) );
}
компилирует. Вот живая демонстрация. Посмотрите на следующий вопрос, хотя!
Является
C
считается удовлетворяющимLessThanComparable
концепция?
№ Требования LessThanComparable
Концепция заключается в том, что для объектов x
а также y
типа C
или же const C
выражение x<y
является действительным и неявно конвертируемым в bool и <
Оператор устанавливает строгое отношение слабого порядка. В вашем случае объекты const не будут преобразованы в int
s. Это ошибка в вашем коде, потому что она не является правильной. Добавление const
Ключевое слово заставит его работать и класс C
действительно будет LessThanComparable
, Строгое слабое отношение порядка выполняется, потому что int
s выполнить это требование.
Будет
C
соответствовать требованиям гипотетического концептуализированного алгоритма
библиотека, которая требует, чтобы тип былLessThanComparable
,
Если вы исправите свое постоянство, да, это будет.
Несколько sidenotes:
GCC 4.9 компилирует x<y
даже если x
а также y
имеют тип const C
, Это похоже на ошибку компилятора, так как GCC 5.2 и clang 3.6 выдают здесь ошибку времени компиляции.
Переходя std::less<C>()
в качестве дополнительного аргумента std::sort()
дает ошибку времени компиляции, потому что функция сравнения требует, чтобы постоянные объекты были сравнимыми в этом случае. Однако, проходя std::less<void>()
ничего не нарушает, так как аргументы отлично передаются.
std::sort()
алгоритм не требует полного LessThanComparable
, но концепция Compare
, Кроме того, тип итератора должен быть RandomAccessIterator
то есть ValueSwappable
и разыменованный тип должен быть MoveContructable
а также MoveAssignable
, Это все относится к вашему первому вопросу, даже если ошибка константности не исправлена. Вот почему std::sort()
и другие стандартные алгоритмы работают.
Нет. Компилятор не может сделать такую большую магию, то есть вызвать метод cast и затем применить <
оператор. Представьте, что есть несколько операторов приведения для разных типов, как бы компилятор выбрал правильный?
РЕДАКТИРОВАТЬ: На самом деле это не правильно. Пока есть один оператор приведения, это будет работать. Но с двумя или более компилятор будет жаловаться на неоднозначное приведение. Тем не менее, этот подход очень хрупкий, так что в целом это не очень хорошая идея.
Я попробовал пример, предложенный Мердад Момены. Работало нормально. Однако, с небольшим редактированием, это больше не работает.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
struct C
{
C(int x):X(x){}
operator int() { return X; }
operator float() { return static_cast<float>(X); }
int X;
};
using namespace std;
int main()
{
vector<C> u = {1, 2, 35, 6, 3, 7, 8, 9, 10};
sort(u.begin(), u.end());
for(auto x: u){
cout << x << endl;
}
}
Потому что это приведет к двусмысленности. Так что не стоит делать это так.