Re[17]: Когда это наконец станет defined behavior?
От: σ  
Дата: 05.05.23 08:29
Оценка:
S>>>Если bar получает константную ссылку на S, то оно вообще не должно скомпилироваться: https://wandbox.org/permlink/QmsGOIVldZJHwUCM

σ>>Ой-вей, сложно кастануть? Я типа псевдокода запостил.


S>Как только мы выполняем const_cast, мы вступаем на поле UB.


Подробнее.
Re[14]: Когда это наконец станет defined behavior?
От: T4r4sB Россия  
Дата: 05.05.23 08:30
Оценка:
Здравствуйте, σ, Вы писали:

σ>Можно.


Тогда я не понимаю эту фигню с лаундером. В каком случае он нужен?
Re[18]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 05.05.23 08:37
Оценка:
Здравствуйте, σ, Вы писали:

S>>>>Если bar получает константную ссылку на S, то оно вообще не должно скомпилироваться: https://wandbox.org/permlink/QmsGOIVldZJHwUCM


σ>>>Ой-вей, сложно кастануть? Я типа псевдокода запостил.


S>>Как только мы выполняем const_cast, мы вступаем на поле UB.


σ>Подробнее.


Внутри bar неизвестно, передали ли в bar константную ссылку на константный объект или на неконстантный. Соответственно, когда мы в bar делаем const_cast и снимаем константность, то мы можем оказаться в ситуации, когда получили ссылку на реально константный объект, сняли с него константность и получили UB.
Re[15]: Когда это наконец станет defined behavior?
От: σ  
Дата: 05.05.23 08:38
Оценка:
σ>>Можно.

TB>Тогда я не понимаю эту фигню с лаундером. В каком случае он нужен?


https://timsong-cpp.github.io/cppwp/n4868/ptr.launder#example-1
(раньше ограничения были строже, ср. с https://timsong-cpp.github.io/cppwp/n4659/ptr.launder#5)
Re[19]: Когда это наконец станет defined behavior?
От: σ  
Дата: 05.05.23 08:46
Оценка:
S>когда мы в bar делаем const_cast и снимаем константность, то мы можем оказаться в ситуации

А можем не оказаться.
Re[20]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 05.05.23 08:50
Оценка:
Здравствуйте, σ, Вы писали:

S>>когда мы в bar делаем const_cast и снимаем константность, то мы можем оказаться в ситуации


σ>А можем не оказаться.


О том и речь, что ответ "может" не совсем точен. По хорошему, он должен быть дополнен оговорками.
Re[21]: Когда это наконец станет defined behavior?
От: rg45 СССР  
Дата: 05.05.23 08:56
Оценка:
Здравствуйте, so5team, Вы писали:

σ>>А можем не оказаться.


S>О том и речь, что ответ "может" не совсем точен. По хорошему, он должен быть дополнен оговорками.


Как я понял, это "можно" следует относить к конткретному примеру, когда мы хаха, убираем const в строке 8
Автор: T4r4sB
Дата: 04.05.23
. Хотя, мой стеклянный шар частенько подводит меня в последнее время.

P.S. И это отвечает на вопрос, почему компиляторы убирают оптимизацию при снятии константности с объекта "s".
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.05.2023 9:11 rg45 . Предыдущая версия . Еще …
Отредактировано 05.05.2023 8:57 rg45 . Предыдущая версия .
Re[22]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 05.05.23 09:13
Оценка:
Здравствуйте, rg45, Вы писали:

S>>О том и речь, что ответ "может" не совсем точен. По хорошему, он должен быть дополнен оговорками.


R>Как я понял, это "можно" следует относить к конткретному примеру, когда мы хаха, убираем const в строке 8
Автор: T4r4sB
Дата: 04.05.23
. Хотя, мой стеклянный шар частенько подводит меня в последнее время.


Вероятно.

Я думаю, что здесь можно (нужно?) смотреть на происходящее с двух точек зрения:

1) снаружи bar экземпляр типа S не константен, следовательно, при передаче его в bar можно ожидать чего угодно, в том числе и const_cast с последущей модификаций. Что не позволяет оптимизатору делать какие-то предположения;

2) внутри bar мы можем предполагать, что получили ссылку на неконстантный объект и что const_cast безопасен. Но гарантий нет.

Соответственно, как только внутри bar появляется const_cast, так у нас появляются и шансы нарваться на UB.
Re[23]: Когда это наконец станет defined behavior?
От: rg45 СССР  
Дата: 05.05.23 09:20
Оценка:
Здравствуйте, so5team, Вы писали:

S>Соответственно, как только внутри bar появляется const_cast, так у нас появляются и шансы нарваться на UB.


В данном сценарии то, что происходит внутри bar — это откровенный говнокод. Но при компиляции внешнего кода, который вызывает bar, компилятор видит, что, даже если подобный говнокод имеет место быть, то он не приведет к UB. Значит, компилятор обязан корректно обработать в т.ч. и этот сценарий.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[24]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 05.05.23 09:29
Оценка:
Здравствуйте, rg45, Вы писали:

R>В данном сценарии то, что происходит внутри bar — это откровенный говнокод.


В связи с тем, что можно прочитать по ссылке от ув.σ (https://timsong-cpp.github.io/cppwp/n4868/ptr.launder#example-1):
struct X { int n; };
const X *p = new const X{3};
const int a = p->n;
new (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const
const int b = p->n;                 // undefined behavior
const int c = std::launder(p)->n;   // OK

я уже не могу позволить себе быть столь категоричным.

Меня даже больше интересует, а не нужно ли после возвращения из bar вот здесь:
int foo() {
    const S s{1};
    int i1 = s.i;
    bar(s);
    int i2 = s.i; // (1)
    return i1 + i2;
}

сделать std::launder в точке (1). Поскольку lifetime для объекта s закончился внутри bar...
Re[25]: Когда это наконец станет defined behavior?
От: rg45 СССР  
Дата: 05.05.23 09:34
Оценка:
Здравствуйте, so5team, Вы писали:


R>>В данном сценарии то, что происходит внутри bar — это откровенный говнокод.


S>В связи с тем, что можно прочитать по ссылке от ув.σ (https://timsong-cpp.github.io/cppwp/n4868/ptr.launder#example-1):


Говнокод в том смысле, что внутри функции bar действительно может порождаться UB. Мы же не видим места, откуда нас вызвали и ничего не знаем о константности объекта, ссылку на который нам передали. В одном случае UB может не быть, а в другом может быть. Приличные функции таких фортелей себе не позволяют.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 05.05.2023 9:38 rg45 . Предыдущая версия . Еще …
Отредактировано 05.05.2023 9:37 rg45 . Предыдущая версия .
Re[25]: Когда это наконец станет defined behavior?
От: σ  
Дата: 05.05.23 10:42
Оценка:
S>Меня даже больше интересует, а не нужно ли

Не нужно.
Re[18]: Когда это наконец станет defined behavior?
От: B0FEE664  
Дата: 05.05.23 10:49
Оценка: 11 (1) +1
Здравствуйте, rg45, Вы писали:

R>Хочется ясности.

Ссылка на p0532r0.pdf приведённая T4r4sB
Автор: T4r4sB
Дата: 04.05.23
многое проясняет:
Константный объект не может (без UB) быть изменён пока объект жив, но жизнь константного объекта можно закончить (если он подобъект неконстантного объекта), а на его месте создать новый объект с другим значением. (Поэтому в стандарте есть оговорка "during its lifetime").
Компилятору сложно отследить пересоздание константного объекта из-за того, что могут быть использованы самописные алокаторы. Проблема усугубляется тем, что требования к аллокаторам плохо совместимы с требованиями к placment new (хотя для меня этот вопрос до конца не ясен).
В целом получается, что есть много старого кода формально с UB и это мешает оптимизации, в том числе при вызове виртуальных функций. Причём UB не удаётся убрать правками стандарта.
И каждый день — без права на ошибку...
Re[26]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 05.05.23 10:57
Оценка:
Здравствуйте, σ, Вы писали:

S>>Меня даже больше интересует, а не нужно ли


σ>Не нужно.


А чем обсуждаемая ситуация:
void bar(const S & s) {
    new(const_cast<S&>(&s)) S{0};
}
 
int foo() {
    S s{1};
    int i1 = s.i;
    bar(s);
    int i2 = s.i; // (1)
    return i1 + i2;
}


отличается от примера, приведенного вот здесь: https://miyuki.github.io/2016/10/21/std-launder.html , а именно:
struct A {
  virtual int f();
};

struct B : A {
  virtual int f() { new (this) A; return 1; }
};

int A::f() { new (this) B; return 2; }

int h() {
  A a;
  int n = a.f();
  int m = std::launder(&a)->f();
  return n + m;
}


?
Re[27]: Когда это наконец станет defined behavior?
От: σ  
Дата: 05.05.23 16:57
Оценка: 6 (1)
S>>>Меня даже больше интересует, а не нужно ли

σ>>Не нужно.


S>А чем обсуждаемая ситуация:

S>
void bar(const S & s) {
    new(const_cast<S&>(&s)) S{0};
}
 
int foo() {
    S s{1};


Так, стоп. В сообщении про нужно/не нужно
Автор: so5team
Дата: 05.05.23
в коде const S s{1};
Впрочем, на ответ «не нужно» это не влияет.

S>отличается от примера, приведенного вот здесь: https://miyuki.github.io/2016/10/21/std-launder.html


Тем, что тип объекта не меняется
Re[28]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 05.05.23 18:24
Оценка:
Здравствуйте, σ, Вы писали:

S>>А чем обсуждаемая ситуация:

S>>
σ>void bar(const S & s) {
σ>    new(const_cast<S&>(&s)) S{0};
σ>}
 
σ>int foo() {
σ>    S s{1};
σ>


σ>Так, стоп. В сообщении про нужно/не нужно
Автор: so5team
Дата: 05.05.23
в коде const S s{1};


Так ведь если в foo() стоит const S s{1}, то изменение его в bar -- это UB?
Или константные объекты разрешено менять через placement new?

S>>отличается от примера, приведенного вот здесь: https://miyuki.github.io/2016/10/21/std-launder.html


σ>Тем, что тип объекта не меняется


Но в примере из стандарта:
struct X { int n; };
const X *p = new const X{3};
const int a = p->n;
new (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const
const int b = p->n;                 // undefined behavior
const int c = std::launder(p)->n;   // OK

тип объекта не меняется, но launder звать нужно.
Re[29]: Когда это наконец станет defined behavior?
От: rg45 СССР  
Дата: 05.05.23 18:31
Оценка:
Здравствуйте, so5team, Вы писали:

S>Так ведь если в foo() стоит const S s{1}, то изменение его в bar -- это UB?

S>Или константные объекты разрешено менять через placement new?

Думаю, это UB, без вариантов: https://timsong-cpp.github.io/cppwp/dcl.type.cv#4
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[29]: Когда это наконец станет defined behavior?
От: σ  
Дата: 05.05.23 18:38
Оценка: 12 (1)
S>Так ведь если в foo() стоит const S s{1}, то изменение его в bar -- это UB?
S>Или константные объекты разрешено менять через placement new?

https://timsong-cpp.github.io/cppwp/n4868/basic.life#10

S>>>отличается от примера, приведенного вот здесь: https://miyuki.github.io/2016/10/21/std-launder.html


σ>>Тем, что тип объекта не меняется


S>Но в примере из стандарта:

S>
struct X { int n; };
const X *p = new const X{3};
const int a = p->n;
new (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const
const int b = p->n;                 // undefined behavior
const int c = std::launder(p)->n;   // OK

S>тип объекта не меняется, но launder звать нужно.

https://timsong-cpp.github.io/cppwp/n4868/basic.life#8.3
Re[35]: Когда это наконец станет defined behavior?
От: kov_serg Россия  
Дата: 11.05.23 09:36
Оценка:
Здравствуйте, rg45, Вы писали:

R>ты хочешь меня в чем-то убедить


Попробую сформулировать претензии к const
1. этот модификатор создаёт дополнительный тип. На ровном месте число сущностей удваивается, а в случае контейнеров может и учетверяться и так далее. Для их обработки приходится писать разные методы
2. сам по себе он не гарантирует неизменность данных. в некоторых случаях даже нет возможности это отловить
3. очень узкоспециализированный (пытается описать только неизменность)
4. заставляет компилятор заниматься ненужным анализом и творить чудеса UB-строения
В то время как вместо этого модификатора нужны языковые конструкции которые описывают инварианты структур(классов) которые можно проверять при отладке и выявить их нарушения, а в релизе полагать что это заведомо выполняется в любых ситуациях и не проверять. При этом какие-то инварианты могут выполняться всегда (a=b-c или a<=b<=c ...), а какие-то при входе в метод и при выходе из него. Т.е. функция может нарушать инварианты локально но по выходу обязуется из восстановить.
Например инвариант неизменность переменной (аля const) или упорядоченность по возрастанию или то что данные удовлетворяют каким-то особым правилам куча, все поля валидны, бинарное дерево с высотами веток отличающимися не более чем на единицу или же граф без циклов или то что время выполнения будет ограничено и т.п. Более того ряд функций могут явно не соблюдать эти инварианты, но это тоже должно быть указано явно.
Re[36]: Когда это наконец станет defined behavior?
От: rg45 СССР  
Дата: 11.05.23 20:24
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>1. этот модификатор создаёт дополнительный тип. На ровном месте число сущностей удваивается, а в случае контейнеров может и учетверяться и так далее. Для их обработки приходится писать разные методы


Не согласен. Сам по себе модификатор const не вынуждает писать дополнительные методы. Он ДАЕТ ВОЗМОЖНОСТЬ программисту предоставить разные версии функций-членов для константного и неконстантного объектов — только в том случае, если это нужно! Конечно, в каких-то простейших случаях могут возникать похожие на вид-функции члены, которые выглядят как дублирование, но это очень поверхностный взгляд, это во-первых. Во-вторых, необходимость создания разных методов не является ни общим случаем, ни, тем более единственным — все зависит от семантики и дизайна класса. Например, во многих случаях бывает достаточно одной только версии — константной. Кроме того никто не запрещает константным версиям возвращать неконстантные указатели и ссылки. Как пример — все методы доступа к данным умных указателей стандартной библиотеки: get(), operator*, operator-> и пр. — все эти методы существуют только в одном варианте — в константном, а ссылки и указатели возвращают в соответствии с типом указателя. Если у тебя регулярно возникает необходимость определения всех возможных комбинаций const/volatile/lvalue-/rvalue-reference, нужных и ненужных, то, возможно, у тебя какие-то системные проблемы с составлением дизайна. По этому пункту ты меня не убедил.

_>2. сам по себе он не гарантирует неизменность данных. в некоторых случаях даже нет возможности это отловить


В каких-то случаях гарантирует (в well-formed программе), если модификатор относится непосредственно к объекту. В каких-то случаях, если модификатор пришел со ссылкой, у него просто другая семантика — но он является средством выдачи прав на чтение/запись. То, что он не гарантирует неизменности, не означает, что он бесполезен. По этому пункту тоже не убедил.

_>3. очень узкоспециализированный (пытается описать только неизменность)


Так так и должно быть — const ни на что, кроме константности влиять и не должен. Опять не убедил.


_>4. заставляет компилятор заниматься ненужным анализом и творить чудеса UB-строения


Ну вот, опять "заставляет". Не "заставляет", а "дает возможность" — для оптимизаций. И оптимизации — дело добровольное — зависят исключительно от воли разработчиков компилятора.

Дальше вообще какая-то фантастика пошла. Не убедил ни по одному пункту.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 11.05.2023 20:43 rg45 . Предыдущая версия . Еще …
Отредактировано 11.05.2023 20:41 rg45 . Предыдущая версия .
Отредактировано 11.05.2023 20:27 rg45 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.