A const object is an object of type const T or a non-mutable subobject of a const object.
Except for array types, a compound type ([basic.compound]) is not cv-qualified by the cv-qualifiers (if any) of the types from which it is compounded.
После снятия константности с объекта "s", "i" перестал быть подобъектом константного объекта, а значит и сам перестал быть константным объектом. Следовательно и пункт, в котором декларируется неопределенное поведение, с этого момента на "i" не распространяется:
Any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr]) a const object (basic.type.qualifier) during its lifetime ([basic.life]) results in undefined behavior.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>После снятия константности с объекта "s", "i" перестал быть подобъектом константного объекта, а значит и сам перестал быть константным объектом.
Кроме того, там есть ссылка на документ, в котором приведен пример с placement new, где есть УБ, но по факту даже кланг боится убирать лишнее чтение из памяти
Я должен честно признаться — я не уверен в том, что сказал выше. Это на правах версии. В частности, я не вижу препятствий к тому, чтоб первую часть опрелеления "A const object is an object of type const T" отнести и к подобъекту в т.ч. На мой взгляд, формулировки оставляют желать лучшего в этом месте.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[12]: Когда это наконец станет defined behavior?
R>A const object is an object of type const T or a non-mutable subobject of a const object.
R>
R>Except for array types, a compound type ([basic.compound]) is not cv-qualified by the cv-qualifiers (if any) of the types from which it is compounded.
R>После снятия константности с объекта "s", "i" перестал быть подобъектом константного объекта, а значит и сам перестал быть константным объектом. Следовательно и пункт, в котором декларируется неопределенное поведение, с этого момента на "i" не распространяется:
Это не так. Из того, что сам объект перестал быть константным не следует, что его подобъекты объявленные const перестали быть константными.
Скрытый текст
#include <iostream>
struct S {
const int i;
};
void bar(const S& s)
{
std::cout << "const" << s.i << '\n';
}
void bar(S& s)
{
std::cout << "non const" << s.i << '\n';
}
int foo() {
const S s{1};
bar(s); // s - const
S x{2};
bar(x); // x - non const return 0;
}
int main() { foo(); }
И каждый день — без права на ошибку...
Re[13]: Когда это наконец станет defined behavior?
Здравствуйте, B0FEE664, Вы писали:
BFE>Это не так.
Охотно допускаю, что это не так. Но то, что ты пытаешься привести в качестве доказательства — это фигня на постном масле, а не доказательство. Константностью ссылок невозможно доказать константность объекта.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[14]: Когда это наконец станет defined behavior?
Здравствуйте, rg45, Вы писали:
BFE>>Это не так. R>Охотно допускаю, что это не так.
Это и есть "не так".
R> Но то, что ты пытаешься привести в качестве доказательства — это фигня на постном масле, а не доказательство.
Это не доказательство. это иллюстрация, что неконстантный объект может содержать константные данные и состоять только из константных данных.
R> Константностью ссылок невозможно доказать константность объекта.
Можно, так как неконстантная ссылка не может быть автоматически создана на константный объект.
Но зачем так сложно?
Вот это, естественно, не скомпилируется:
struct S { const int i; };
S x{2};
x.i = 3;
Чем не доказательство, что x.i — константный подобъект?
И каждый день — без права на ошибку...
Re[15]: Когда это наконец станет defined behavior?
Здравствуйте, B0FEE664, Вы писали:
R>> Константностью ссылок невозможно доказать константность объекта. BFE>Можно, так как неконстантная ссылка не может быть автоматически создана на константный объект. BFE>Но зачем так сложно? BFE>Вот это, естественно, не скомпилируется: BFE>
BFE>struct S { const int i; };
BFE>S x{2};
BFE>x.i = 3;
BFE>
BFE>Чем не доказательство, что x.i — константный подобъект?
По этой логике, следующий фрагмент тоже можно пытаться выдать за доказательство константности объекта — это тоже не скомпилируется:
int i;
const int& r = i;
r = 3;
Ссылка на константный объект! А объект-то нифига не константный. Короче, фигня это все, а не доказательства.
Если тебе так уже приспичило что-то доказвать, то докажи, что пример ниже порождает неопределенное поведение, и обоснуй ссылками на стандарт:
struct S { const int i; };
S x{2};
const_cast<int&>(x.i) = 3;
А попутно было бы неплохо также ответить на вопрос
, почему компиляторы убирают оптимизацию при снятии константности с "x". Уж не потому ли, что определение констатного объекта, данное стандартом, допускает двусмысленное толкование?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R> Уж не потому ли, что определение констатного объекта, данное стандартом, допускает двусмысленное толкование?
Я подозреваю, что если считать такое присвоение UB, то тогда, если верить статье https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0532r0.pdf, использование элемента вектора после очистки и пуша — это тоже UB, потому что компилятор может вывести, что адрес такого элемента совпадает с ранее использованным адресом по тому же индексу, и значит константные элементы не меняются.
Пример из статьи:
Здравствуйте, rg45, Вы писали:
R>По этой логике, следующий фрагмент тоже можно пытаться выдать за доказательство константности объекта — это тоже не скомпилируется: R>
R>int i;
R>const int& r = i;
R>r = 3;
R>
R>Ссылка на константный объект! А объект-то нифига не константный. Короче, фигня это все, а не доказательства.
Ссылка — не объект.
R>Если тебе так уже приспичило что-то доказвать, то докажи, что пример ниже порождает неопределенное поведение, и обоснуй ссылками на стандарт: R>
R>struct S { const int i; };
R>S x{2};
R>const_cast<int&>(x.i) = 3;
R>
С++23 n4944
9.2.9.2/4:
Any attempt to modify (7.6.19, 7.6.1.6, 7.6.2.3) a const object (6.8.5) during its lifetime (6.7.3) results in undefined behavior.
6.8.5/1.1:
A const object is an object of type const T or a non-mutable subobject of a const object.
И даже специальная заметка:
7.6.1.11/6:
[Note 2 : Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member
resulting from a const_cast that casts away a const-qualifier60 can produce undefined behavior (9.2.9.2). —end
note]
Так что формально это undefined behavior.
Что смущает-то?
R>А попутно было бы неплохо также ответить на вопрос
, почему компиляторы убирают оптимизацию при снятии константности с "x". Уж не потому ли, что определение констатного объекта, данное стандартом, допускает двусмысленное толкование?
Да мало ли может быть причин не относящихся к стандарту?
И каждый день — без права на ошибку...
Re[17]: Когда это наконец станет defined behavior?
Здравствуйте, T4r4sB, Вы писали:
TB>Я подозреваю, что если считать такое присвоение UB, то тогда, если верить статье https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0532r0.pdf, использование элемента вектора после очистки и пуша — это тоже UB, потому что компилятор может вывести, что адрес такого элемента совпадает с ранее использованным адресом по тому же индексу, и значит константные элементы не меняются.
В статье про время жизни объектов, а не про изменение константного объекта во время его жизни.
TB>Выглядит всё так, будто авторы стандарта со своими UB опять трахнули в мозг сами себя.
Согласен.
И каждый день — без права на ошибку...
Re[17]: Когда это наконец станет defined behavior?
Здравствуйте, B0FEE664, Вы писали:
BFE>6.8.5/1.1: BFE>
BFE>A const object is an object of type const T or a non-mutable subobject of a const object.
BFE>И даже специальная заметка: BFE>7.6.1.11/6: BFE>
BFE>[Note 2 : Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member
BFE>resulting from a const_cast that casts away a const-qualifier60 can produce undefined behavior (9.2.9.2). —end
BFE>note]
BFE>Так что формально это undefined behavior. BFE>Что смущает-то?
Согласен, выглядит убедительно.
BFE>Да мало ли может быть причин не относящихся к стандарту?
Хочется ясности.
--
Не можешь достичь желаемого — пожелай достигнутого.
W>>Конечно он может это сделать: https://godbolt.org/z/T5MG743aW
TB>Хаха убираем const в строке 8 и даже продвинутый кланг забоялся делать предположения о КОНСТантном поле структуры
void bar(const S& s) может быть определена как
void bar(const S& s)
{
::new (&s) S { /* новое значение для s.i */ };
}
?
Re[12]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
S>>Если bar получает константную ссылку на S, то оно вообще не должно скомпилироваться: https://wandbox.org/permlink/QmsGOIVldZJHwUCM
σ>Ой-вей, сложно кастануть? Я типа псевдокода запостил.
Как только мы выполняем const_cast, мы вступаем на поле UB.
Соответственно, ответом на вопрос "Не знаю, а с точки зрения стандарта и UB так можно?" вряд ли может быть "можно".