Почему я получаю ошибку компиляции для этой программы в g++ 4.8.5?

Я пытаюсь решить проблему от интернет-судьи, и судья использует g++ 4.8.5.

Следующая программа правильно компилируется на моей машине (g++ 8.2.0) с -std=c++11 -pedantic-errors:

#include <algorithm>

struct Task {
    int deadline;
    const bool operator<(const Task &o) {
        return deadline < o.deadline;
    }
};
Task tasks[] = {8, 4, 3, 5, 1, 2, 0, 7};

int main()
{
    std::sort(tasks, tasks + 8);
}

Однако судья дает мне следующие ошибки:

In file included from /usr/include/c++/4.8/algorithm:62:0,
                 from Main.cpp:1:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of '_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&) [with _RandomAccessIterator = Task*; _Tp = Task]':
/usr/include/c++/4.8/bits/stl_algo.h:2283:70: required from '_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = Task*]' /usr/include/c++/4.8/bits/stl_algo.h:2315:54:
required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = Task*; _Size = int]' /usr/include/c++/4.8/bits/stl_algo.h:5461:36:
required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = Task*]' Main.cpp:15:23:
required from here /usr/include/c++/4.8/bits/stl_algo.h:2245:19:
error: passing 'const Task' as 'this' argument of 'const bool Task::operator<(const Task&)' discards qualifiers [-fpermissive]
    while (__pivot < *__last)
       ^

Судья составляет -std=c++11 -O2 -lm,

G ++ 4.8 не полностью поддерживает C++11? Как мне скомпилировать это?

3 ответа

Решение

Да, GCC 4.8 поддерживает большую часть C++11, что можно увидеть здесь. Тем не менее, это, кажется, ошибка в GCC 4.8. Точные требования std::sort расположены в разделе 25.4 настоящей спецификации ISO с 2013 года.

Там отмечается, что единственным требованием к operator< является то, что он реализует " строгий слабый порядок". Затем он продолжает определять "строгий слабый порядок" по своим математическим свойствам. Ничто из этого не означает, что operator< должно быть const, как GCC 4.8 пытался форсировать. operator< возможно, может изменить внутреннюю переменную и все еще следовать спецификации, пока возвращаемые логические значения делают "строгий слабый порядок". Это можно использовать для подсчета количества сравнений, сделанных по каждой переменной std::sort функция, позволяющая облегчить сравнительный анализ std::sort не вдаваясь в неопределенное поведение (как один из примеров множества разных возможностей).

Использование const должно было переусердствовать в исходной реализации C++ 11 в GCC 4.8 и было исправлено в более поздних версиях.

К сожалению, если онлайн-судья использует эту версию GCC, вы ничего не можете с этим поделать. Другие ответы здесь определяют, как это исправить (а именно, сделать вашу функцию-член const).

Копаясь в истории GCC, мы видим, что она была изменена здесь, 2013-09-27. Это казалось большим рефактором, который, возможно, не обратил внимания на тонкости, но вкладчик действительно удалил const в нескольких областях, так что это казалось преднамеренным. Сообщение коммита также не слишком поучительно. Если вы хотите, вы можете написать ему, посмотреть, помнит ли он xD

const bool operator<(const Task &o) {

должно быть

bool operator<(const Task &o) const {

Возвращаемое значение не имеет смысла constи как оператор сравнения не нужно изменять *this,

Сообщение об ошибке говорит passing 'const Task' as 'this' argument of 'const bool Task::operator<(const Task&)' discards qualifiersтак где-то в недрах std::sort он пытается позвонить operator< на const Task объект. Ваш оригинал tasks массив не const, так что это, вероятно, потому что std::sort вызывает вспомогательную функцию, которая принимает const Task & (потому что вспомогательная функция не должна ничего изменять).

Вызов не удается, потому что ваш operator< не был объявлен как const (т.е. вызывается на const объект).

Я не уверен, что отличает G ++ 8.2, но, видимо, реализация std::sort изменилось, так что это не относится к const T объекты внутри больше.

Обратите внимание на эту строку в сообщении об ошибке

error: passing 'const Task' as 'this' argument of 'const bool Task::operator<(const Task&)' discards qualifiers

std::sort ожидает operator< для вашего объекта, чтобы не изменять сам объект. Вам нужно указать тот факт, что ваш оператор сравнения не изменяет состояние объекта, явно пометив его как const,

Правильная версия будет выглядеть примерно так

struct Task {
    int deadline;
    const bool operator<(const Task &o) const {
        return deadline < o.deadline;
    }
};

Обратитесь к этой ссылке для получения дополнительной информации: Значение 'const' последний в объявлении функции класса?

Другие вопросы по тегам