Меньше, чем оператор через неявное преобразование?


Рассмотрим следующий класс:

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

Мой вопрос:

  • можно ли использовать C в стандартных алгоритмах, таких как std::sort, которые в настоящее время используют оператор
  • считается, что C удовлетворяет LessThanComparable концепция?
  • будет соответствовать требованиям гипотетической концептуальной библиотеки алгоритмов, которая требует, чтобы тип был LessThanComparable.
3 16

3 ответа:

Является 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 справедливо и неявно преобразуется в bool, а оператор < устанавливает строгое слабое отношение упорядочения. В вашем случае const objects do не преобразуется в ints. это ошибка в вашем коде, потому что он не является корректным const. Добавление ключевого слова const сделает его работоспособным, и класс C действительно будет LessThanComparable. Строгое слабое упорядочивающее отношение выполняется, потому что int s выполняют это требование.

Будет C отвечать требованиям гипотетический концептуализированный алгоритм библиотека, для которой требуется Тип LessThanComparable.

Если вы исправите свою постоянность, да, это будет.

Несколько примечаний:

  • 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. Это все относится к вашему первому вопросу, даже если ошибка constness не исправлена. Вот почему std::sort() и другие стандартные алгоритмы работают.

Нет. Компилятор не может сделать такую большую магию, то есть вызвать метод cast и затем применить оператор <. Представьте, что существует несколько операторов приведения для разных типов, как компилятор выберет правильный?

EDIT: на самом деле это не так. Пока есть один оператор приведения, это будет работать. Но с двумя или более компилятор будет жаловаться на неоднозначное приведение. Однако этот подход очень хрупок, так что в целом это не очень хорошая идея.

Я попробовал пример, предложенный mehrdad momeny. Это сработало отлично. Однако при небольшом редактировании он больше не работает.

#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;
    }
}

Live Demo

Потому что это приведет к двусмысленности. Так что, это не очень хорошая идея, чтобы сделать это так.