Подтвердить что ты не робот

Могу ли я потерять "constness" в возвращаемом типе переопределяющей виртуальной функции?

Следующий код компилируется и запускается, и никакие предупреждения не выдаются ни gcc, ни clang:

#include <iostream>

struct Base {
    virtual ~Base() = default;
    virtual std::string const& get() = 0;
};

struct Derived: Base {
    virtual std::string& get() override { return m; }
    std::string m;
};

int main()
{
    Derived d;
    d.get() = "Hello, World";

    Base& b = d;
    std::cout << b.get() << "\n";
}

Является ли std::string& ковариантным с std::string const&, то?

4b9b3361

Ответ 1

Да

Это указано в class.virtual, в последнем черновике (n4606) мы видим:

§10.3 7/ Возвращаемый тип функции переопределения должен быть либо идентичен возвращаемому типу переопределенной функции или ковариантно с классами функций. Если функция D::f переопределяет функцию B::f, возвращаемые типы функций ковариантны, если они удовлетворяют следующим критериям:

  • оба являются указателями на классы, оба являются значениями lvalue для классов или оба являются ссылками rvalue на классы 111
  • класс возвращаемого типа B::f является тем же классом, что и класс возвращаемого типа D::f, или является однозначным и доступным прямым или косвенным базовым классом класса в возвращаемом типе D::f
  • оба указателя или ссылки имеют одинаковую cv-квалификацию, а тип класса в возвращаемом типе D::f имеет ту же самую cv-квалификацию, что или менее cv-qualification, чем тип класса в возвращаемом типе B::f.

В частности, последняя точка относится именно к этому случаю: допустимо, чтобы переопределяющий тип потерял квалификаторы const и/или volatile (однако он не может их получить).


Примечание: как упоминалось в @george выше, пункт 8/используется для предотвращения этого от работы с неполными типами классов, но это было с фиксированной.