Должен ли UB вызывать неконстантный метод в константном экземпляре, когда метод не изменяет членов? - PullRequest
6 голосов
/ 01 октября 2019

Код говорит более тысячи слов, так что ...

Это неопределенное поведение для мутирования const int:

struct foo {
    int x;
    void modify() { x = 3; }
};

void test_foo(const foo& f) {
    const_cast<foo&>(f).modify();
}

int main(){
    const foo f{2};
    test_foo(f);
}

Как насчет этого:

struct bar {
    void no_modify() { }
};

void test_bar(const bar& b) {
    const_cast<bar&>(b).no_modify();
}

int main(){
    const bar b;
    test_bar(b);
}

Разрешено ли вызывать неконстантный метод для константного объекта (через const_cast), когда метод не изменяет объект?

PS : Я знаю, что no_modify должен был быть объявлен как const, и тогда вопрос не имеет смысла, но предположим, что определение bar не может измениться.

PPS : Просто будьтеконечно: не делайте этого дома (или где-либо еще). Я бы никогда не позволил такому коду пройти проверку. В ролях можно избежать тривиально. Это вопрос языка юриста.

Ответы [ 2 ]

4 голосов
/ 01 октября 2019

Поведение вашего кода четко определено.

Единственное, что имеет значение, - это если вы действительно измените объект. Вы неВсе, что вы делаете, это вызываете функцию-член, и эта функция не изменяет объект.

1 голос
/ 01 октября 2019

В стандарте C ++ 14 N4296, к которому у меня есть доступ, мы видим примечание в 5.2.11 / 6:

[Примечание: в зависимости от типа объекта, операция записичерез указатель, lvalue или указатель на элемент данных, полученный в результате const_cast, который отбрасывает const-qualifier74, может привести к неопределенному поведению (7.1.6.1). - конец примечания]

Технически я подозреваю, что примечание может быть не нормативным, но кажется очевидным, что здесь подразумевается, что удаление константности становится неопределенным поведением только при попытке записи через указатель /ссылка (возможно, для поддержки устаревшего кода, который не соответствует правильной константности).

...