Re[94]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 21.08.23 13:04
Оценка:
Здравствуйте, σ, Вы писали:

S>>Оно понятно, что в C++23 появился std::start_lifetime_as, посредством которого можно сделать:

S>>
σ>alignas(T) std::byte buffer[sizeof(T)];
σ>read_some_data(buffer);
σ>const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);
σ>

S>>Но в этом случае мы, по сути имеем лишь константный указатель на неконстантный объект.

σ>std::start_lifetime_as<const T> создаёт объект


Создает? Да ладно!

Он, вроде бы, к созданию объекта чуть меньше, чем никак. Это всего лишь указание компилятору считать полученный указатель валидным указателем на объект, время жизни которого было начато вне поля зрения компилятора.
Отредактировано 21.08.2023 13:05 so5team . Предыдущая версия .
Re[95]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 13:15
Оценка: +1
σ>>std::start_lifetime_as<const T> создаёт объект

S>Создает? Да ладно!


???

Effects: Implicitly creates objects within the denoted region consisting of an object a of type T
Отредактировано 21.08.2023 13:23 σ . Предыдущая версия .
Re[96]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 21.08.23 13:30
Оценка:
Здравствуйте, σ, Вы писали:

σ>>>std::start_lifetime_as<const T> создаёт объект


S>>Создает? Да ладно!


σ>Effects: Implicitly creates objects within the denoted region consisting of an object a of type T


И?

Вот у нас два примера. Первый:
alignas(T) std::byte buffer[sizeof(T)];
read_some_data(buffer); // (1) собственно здесь создание объекта и происходит.
const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);


Второй:
alignas(T) std::byte buffer[sizeof(T)]; // Какой-то мусор.
const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);


Ну и как std::start_lifetime_as создаст во втором случае объект типа T? И откуда он возьмет его корректный начальный инвариант?

В том-то и дело, что implicitly creates -- это такое высказывание для стандарта, которое означает начало времени жизни для объекта, который был создан вне поля видимости компилятора. Отсюда и всякие implicit-lifetime types, implicitly creates и пр.
Re[97]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 13:53
Оценка: +1
S>Здравствуйте, σ, Вы писали:

σ>>>>std::start_lifetime_as<const T> создаёт объект


S>>>Создает? Да ладно!


σ>>Effects: Implicitly creates objects within the denoted region consisting of an object a of type T


S>И?


S>Вот у нас два примера. Первый:

S>
alignas(T) std::byte buffer[sizeof(T)];
read_some_data(buffer); // (1) собственно здесь создание объекта и происходит.
const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);


S>Второй:

S>
alignas(T) std::byte buffer[sizeof(T)]; // Какой-то мусор.
const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);


S>Ну и как std::start_lifetime_as создаст во втором случае объект типа T?


Написано же: implicitly.

S> И откуда он возьмет его корректный начальный инвариант?


Чё возьмёт?! Можно в Preconditions start_lifetime_as увидеть хоть что-то про «корректный начальный инвариант»?

S> В том-то и дело, что implicitly creates -- это такое высказывание для стандарта, которое означает начало времени жизни для объекта


Время жизни объекта в стандарте описывается словами «object lifetime». А создание — create/creates/created etc.

S> который был создан вне поля видимости компилятора.


Когда?! Где?!

Если ты имеешь в виду абстрактную машину C++, то никакие объекты не создаются «вне» её. Был пропозал (или несколько) про «экспорт»/«импорт» объектов из/в абстрактную машину (чтобы работу нескольких процессов через шареную память можно было описать), но они так и остались пропозалами.
Re[94]: Когда это наконец станет defined behavior?
От: T4r4sB Россия  
Дата: 21.08.23 14:26
Оценка:
Здравствуйте, σ, Вы писали:

σ>Разница между программой без UB и с UB — не принципиальна?


Про какие фантастические УБ ты говоришь?
Давай реальный пример, а то пустая болтовня. И походу ты так и не понял в чем разница между объектом и местом в памяти
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[95]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 14:29
Оценка: :)
σ>>Разница между программой без UB и с UB — не принципиальна?

TB>Про какие фантастические УБ ты говоришь?


Читай выше, где я описал разницу между выполнением с NRVO и без. Если при NRVO объект константный, то внутри функции его менять — UB.

TB>Давай реальный пример, а то пустая болтовня.


Define «реальный». Ну и вообще, сначала на мой вопрос про то, какой объект ответь.

TB>И походу ты так и не понял в чем разница между объектом и местом в памяти


Чо за место в памяти? https://timsong-cpp.github.io/cppwp/n4868/intro.memory#def:memory_location, что ли?
Отредактировано 21.08.2023 14:34 σ . Предыдущая версия .
Re[96]: Когда это наконец станет defined behavior?
От: T4r4sB Россия  
Дата: 21.08.23 14:36
Оценка: +1 -1
Здравствуйте, σ, Вы писали:

σ>>>Разница между программой без UB и с UB — не принципиальна?


TB>>Про какие фантастические УБ ты говоришь?


σ>Читай выше, где я описал разницу между выполнением с NRVO и без. Если при NRVO объект константный, то внутри функции его менять — UB.


Обоснуй что это УБ, реальным примером. Иначе получается что ты не умеешь читать стандарт.
Будет смешно если окажется что компилятор считает что семантически объект внутри функции — другой. Хотя и имеет тот же адрес в памяти.

TB>>Давай реальный пример, а то пустая болтовня.


σ>Define «реальный»


Ты тролль или дурачок?
Код который показывает это самое УБ про которое ты говоришь.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[97]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 14:48
Оценка: +1 -1
TB>>>Давай реальный пример, а то пустая болтовня.

σ>>Define «реальный»


TB>Ты тролль или дурачок?


Это понимать как то, что определения не будет?

σ>>>>Разница между программой без UB и с UB — не принципиальна?


TB>>>Про какие фантастические УБ ты говоришь?


σ>>Читай выше, где я описал разницу между выполнением с NRVO и без. Если при NRVO объект константный, то внутри функции его менять — UB.


TB>Обоснуй что это УБ


Ты тролль или дурачок? https://timsong-cpp.github.io/cppwp/n4868/dcl.type.cv#4.sentence-1

TB>Будет смешно если окажется что компилятор считает что семантически объект внутри функции — другой. Хотя и имеет тот же адрес в памяти.


Если по семантике C++ это один и тот же объект, какая разница, что считает компилятор или твой сосед по парте?
Re[98]: Когда это наконец станет defined behavior?
От: T4r4sB Россия  
Дата: 21.08.23 14:52
Оценка:
Здравствуйте, σ, Вы писали:


TB>>>>Давай реальный пример, а то пустая болтовня.


σ>>>Define «реальный»


TB>>Ты тролль или дурачок?


σ>Это понимать как то, что определения не будет?


Уводишь разговор в сторону? Я могу это понимать как слив?

TB>>Обоснуй что это УБ


σ>Ты тролль или дурачок? https://timsong-cpp.github.io/cppwp/n4868/dcl.type.cv#4.sentence-1


Балабол ты форумный, на реальном примере проиллюстрируешь это уб?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[98]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 21.08.23 14:52
Оценка:
Здравствуйте, σ, Вы писали:

S>>Вот у нас два примера. Первый:

S>>
σ>alignas(T) std::byte buffer[sizeof(T)];
σ>read_some_data(buffer); // (1) собственно здесь создание объекта и происходит.
σ>const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);
σ>


S>>Второй:

S>>
σ>alignas(T) std::byte buffer[sizeof(T)]; // Какой-то мусор.
σ>const T * ptr_to_immutable_value = std::start_lifetime_as<const T>(buffer);
σ>


S>>Ну и как std::start_lifetime_as создаст во втором случае объект типа T?


σ>Написано же: implicitly.


Ну так это софистика для стандарта, нужен им был какой-то специальный термин, вот они и придумали для себя implicitly creates.
Обычный разработчик как этот implicitly creates должен воспринимать? Уж точно не как creates, который для new или для обычного создания объекта на стеке.

S>> И откуда он возьмет его корректный начальный инвариант?


σ>Чё возьмёт?!


Нормальное начальное состояние для объекта он где возьмет?

Вот когда мы делаем const T * p = new T(); мы же создаем объект и получаем его в неком нормальном начальном состоянии. Вызвав только new, ничего
больше не делая. А в случае start_lifetime_as мы типа создали, но если до этого пару-тройку обязательных приседаний не сделали, то никакого создания у нас не произойдет.

S>> В том-то и дело, что implicitly creates -- это такое высказывание для стандарта, которое означает начало времени жизни для объекта


σ>Время жизни объекта в стандарте описывается словами «object lifetime». А создание — create/creates/created etc.


Еще раз вам намекаю: то, что написано в стандарте, написано для разработчиков компилятора, анализаторов и стандартной библиотеки.
Пользователям языка текст стандарта нужно на нормальный человеческий язык переводить, чтобы было понимание, что "implicitly creates" к "creates" отношения не имеет.

S>> который был создан вне поля видимости компилятора.


σ>Когда?! Где?!


В первом примере в точке (1).

σ>Если ты имеешь в виду абстрактную машину C++, то никакие объекты не создаются «вне» её.


Я про программы, которые пишут люди. И про людей, которые внезапно сталкиваются с ситуацией, что вот так просто:
unsigned char buffer[4096];
read_data(buffer);
const T * p = reinterpreter_cast<const T>(&buffer[some_offset]);

в C++ поступать нельзя. Потому что компилятор должен понимать откуда у него объекты берутся. И если внезапно появляются объекты, про которые компилятор не знает (как в приводимых мной примерах), то компилятор не будет считать указатель валидным (т.е. указывающим на объект для которого где-то корректно начался lifetime). Отсюда и надобность в start_lifetime_as. И что start_lifetime_as -- это никакое не создание объекта, а суть ублажение компилятора, чтобы он не сотворил каких-то нелепых оптимизаций.

Я, конечно, от души завидую тем, кто понимает что есть абстрактная машина C++ и как эта компилятор работает с этой самой абстрактной машиной. Но, имхо, должны быть и более простые и понятные объяснения принципов работы C++ного кода для обычных людей.
Re[98]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 21.08.23 14:58
Оценка: +1
Здравствуйте, σ, Вы писали:


TB>>>>Про какие фантастические УБ ты говоришь?


σ>>>Читай выше, где я описал разницу между выполнением с NRVO и без. Если при NRVO объект константный, то внутри функции его менять — UB.


TB>>Обоснуй что это УБ


σ>Ты тролль или дурачок? https://timsong-cpp.github.io/cppwp/n4868/dcl.type.cv#4.sentence-1


Только вот фишка в том, что до выхода из функции нет никакого константного объекта. Он появляется только когда функция закончилась. Так что UB будет только если мы попробуем поменять константный объект уже после завершения функции из которого мы объект вернули. Но не до того как.

Ну и я был бы признателен, если бы вы объяснили несведующему, как так получается, что объект константный, но во время работы его конструктора у нас this указывает отнюдь не на константный объект и изменение состояния внутри конструктора через этот указатель никакое не UB.
Re[99]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 15:19
Оценка: +1
TB>>>>>Про какие фантастические УБ ты говоришь?

σ>>>>Читай выше, где я описал разницу между выполнением с NRVO и без. Если при NRVO объект константный, то внутри функции его менять — UB.


TB>>>Обоснуй что это УБ


σ>>Ты тролль или дурачок? https://timsong-cpp.github.io/cppwp/n4868/dcl.type.cv#4.sentence-1


S>Только вот фишка в том, что до выхода из функции нет никакого константного объекта. Он появляется только когда функция закончилась.


Это когда нет NRVO. (И то, скорее константный объект появляется всё-таки до вызова функции, а его инициализация заканчивается (и, следовательно, лайфтайм начинается) после вызова. Ну это так, детали, хер с ними).
А если есть NRVO, то теперь переменная вне функции и внутри, вместо обозначения двух разных объектов, начинают обозначать один и тот же. Я выше кидал цитату про two different ways of referring to the same object.

S>Так что UB будет только если мы попробуем поменять константный объект уже после завершения функции из которого мы объект вернули. Но не до того как.


И каким же образом объект вдруг поменяет свою константность?

S>Ну и я был бы признателен, если бы вы объяснили несведующему, как так получается, что объект константный, но во время работы его конструктора у нас this указывает отнюдь не на константный объект


this во время конструкции константного объекта указаывает, внезапно, на константный объект.

S>изменение состояния внутри конструктора через этот указатель никакое не UB.


Потому что так написано в стандарте https://timsong-cpp.github.io/cppwp/n4868/class.ctor.general#5
Re[92]: Когда это наконец станет defined behavior?
От: B0FEE664  
Дата: 21.08.23 15:22
Оценка: +1
Здравствуйте, σ, Вы писали:

σ>Лол)))

σ>Когда объекта два, то в функции объект неконстантный, а вне — константный и всё просто: можно менять в функции и нельзя вне.
σ>Когда объект один в обоих местах, то он либо константный и там и там, либо не там и не там. Если он константный, то его модифицировать его в функции это UB. А если неконстантный, то его можно модифицировать вне функции, это не UB.

(тихо хихикая) Т.е. согласно вашей логике, исходный пример
std::map<int, int> buildMap() {
    std::map<int, int> result;

    result.insert(42, 43); 
    ...
    return result;
}

const std::map<int, int> someDictionary = buildMap();

— это UB, если NRVO ?

А ничего, что возвращаемый функцией buildMap() тип отличается от типа объекта someDictionary? Не смущает?
И каждый день — без права на ошибку...
Re[93]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 15:32
Оценка: :)
σ>>Лол)))
σ>>Когда объекта два, то в функции объект неконстантный, а вне — константный и всё просто: можно менять в функции и нельзя вне.
σ>>Когда объект один в обоих местах, то он либо константный и там и там, либо не там и не там. Если он константный, то его модифицировать его в функции это UB. А если неконстантный, то его можно модифицировать вне функции, это не UB.

BFE>(тихо хихикая) Т.е. согласно вашей логике, исходный пример

BFE>
std::map<int, int> buildMap() {
    std::map<int, int> result;

    result.insert(42, 43); 
    ...
    return result;
}

const std::map<int, int> someDictionary = buildMap();

BFE>- это UB, если NRVO ?

Может да. Может нет. Может на это сложно/невозможно ответить.
Я об этом спросил у форумчан, но в ответ получил тонну истерики, и ни одной попытки описания поведения со ссылками на стандарт. ¯\_(ツ)_/¯

BFE>А ничего, что возвращаемый функцией buildMap() тип отличается от типа объекта someDictionary? Не смущает?


Сделай глубойкий вдох, убедись, что отличаешь переменные от объектов (и, следовательно, тип переменной от типа объекта), и попробуй сказать, какой же тип у объекта в случае NRVO, т.е. когда переменные result и someDictionary обозначают один и тот же объект.
Re[94]: Когда это наконец станет defined behavior?
От: T4r4sB Россия  
Дата: 21.08.23 15:38
Оценка:
Здравствуйте, σ,
σ>Может да. Может нет. Может на это сложно/невозможно ответить.
Или ты не понимаешь смысл написанного в стандарте
Ты пример где мы можем пронаблюдать UB, покажешь?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[99]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 15:38
Оценка:
S>>> И откуда он возьмет его корректный начальный инвариант?

σ>>Чё возьмёт?!


S>Нормальное начальное состояние для объекта он где возьмет?


S>Вот когда мы делаем const T * p = new T(); мы же создаем объект и получаем его в неком нормальном начальном состоянии. Вызвав только new, ничего

S>больше не делая. А в случае start_lifetime_as мы типа создали, но если до этого пару-тройку обязательных приседаний не сделали, то никакого создания у нас не произойдет.

Я не понимаю, что ты называешь приседаниями.

S>>> В том-то и дело, что implicitly creates -- это такое высказывание для стандарта, которое означает начало времени жизни для объекта


σ>>Время жизни объекта в стандарте описывается словами «object lifetime». А создание — create/creates/created etc.


S>Еще раз вам намекаю: то, что написано в стандарте, написано для разработчиков компилятора, анализаторов и стандартной библиотеки.


Нет, написано для доярок и сталеваров.

S>Пользователям языка текст стандарта нужно на нормальный человеческий язык переводить, чтобы было понимание, что "implicitly creates" к "creates" отношения не имеет.


S>>> который был создан вне поля видимости компилятора.


σ>>Когда?! Где?!


S>В первом примере в точке (1).


σ>>Если ты имеешь в виду абстрактную машину C++, то никакие объекты не создаются «вне» её.


S>Я про программы, которые пишут люди. И про людей, которые внезапно сталкиваются с ситуацией, что вот так просто:

S>
unsigned char buffer[4096];
read_data(buffer);
const T * p = reinterpreter_cast<const T>(&buffer[some_offset]);

S>в C++ поступать нельзя.

Предполагаю, что даже на этом форуме найдутся те, кто скажет что «Это софистика для стандарта. Я всю жизнь так поступал и ничо мне за это не было, так что можно»
Re[95]: Когда это наконец станет defined behavior?
От: σ  
Дата: 21.08.23 15:47
Оценка: +1 -2 :)
σ>>Может да. Может нет. Может на это сложно/невозможно ответить.
TB>Или ты не понимаешь смысл написанного в стандарте
Или ты

TB>Ты пример где мы можем пронаблюдать UB, покажешь?


Пожалуйста:
struct S { int i; };

S f()
{
  S s;

  s.i = 0;
}

const S t = f();

При NRVO, переменные s и t обозначают один и тот же объект.
Если он константный, то его int-овый подобъект это тоже константный объект согласно https://timsong-cpp.github.io/cppwp/n4868/basic.type.qualifier#1.1 (a non-mutable subobject of a const object)
s.i = 0 это модификация (https://timsong-cpp.github.io/cppwp/n4868/expr.ass#2), а модифицировать константный объект — UB (https://timsong-cpp.github.io/cppwp/n4868/dcl.type.cv#4.sentence-1)

Воть :3
Re[100]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 21.08.23 16:04
Оценка:
Здравствуйте, σ, Вы писали:

S>>Вот когда мы делаем const T * p = new T(); мы же создаем объект и получаем его в неком нормальном начальном состоянии. Вызвав только new, ничего

S>>больше не делая. А в случае start_lifetime_as мы типа создали, но если до этого пару-тройку обязательных приседаний не сделали, то никакого создания у нас не произойдет.

σ>Я не понимаю, что ты называешь приседаниями.


Выделение памяти.
Присваивание значения.

Это происходит автоматически при использовании new или при размещении объекта на стеке (или при включения его внутрь другого объекта).

Ничего этого нет для start_lifetime_as.

S>>Еще раз вам намекаю: то, что написано в стандарте, написано для разработчиков компилятора, анализаторов и стандартной библиотеки.


σ>Нет, написано для доярок и сталеваров.


OK, которые специализируются на штудировании стандата для пиления компиляторов, анализаторов и стандартной библиотеки.

σ>Предполагаю, что даже на этом форуме найдутся те, кто скажет что «Это софистика для стандарта. Я всю жизнь так поступал и ничо мне за это не было, так что можно»


Если эти люди простыми словами объяснят что можно делать и почему нужно так, то здорово. А вот отсылки на фразы типа "implicitly creates..." таким описанием, к сожалению, не являются.
Re[96]: Когда это наконец станет defined behavior?
От: T4r4sB Россия  
Дата: 21.08.23 16:08
Оценка: :)
Здравствуйте, σ, Вы писали:

TB>>Ты пример где мы можем пронаблюдать UB, покажешь?


σ>Пожалуйста:

σ>
struct S { int i; };

σ>S f()
σ>{
σ>  S s;

σ>  s.i = 0;
σ>}

σ>const S t = f();


Ну и где тут наблюдаемое уб?
Будешь придуриваться и делать вид что не понимаешь выделенное слово?

Не надо мне кивать на твое кривое толкование стандарта, покажи на онлайн компиляторе, как режимы оптимизации ломают ожидаемую логику.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[94]: Когда это наконец станет defined behavior?
От: so5team https://stiffstream.com
Дата: 21.08.23 16:11
Оценка:
Здравствуйте, σ, Вы писали:

BFE>>А ничего, что возвращаемый функцией buildMap() тип отличается от типа объекта someDictionary? Не смущает?


σ>Сделай глубойкий вдох, убедись, что отличаешь переменные от объектов (и, следовательно, тип переменной от типа объекта), и попробуй сказать, какой же тип у объекта в случае NRVO, т.е. когда переменные result и someDictionary обозначают один и тот же объект.


Да блин, возьмите исходный пример:
std::map<int, int> buildMap() {
    std::map<int, int> result;

    result.insert(42, 43); 
    ...
    return result;
}

void useMap() {
    const std::map<int, int> someDictionary = buildMap();
    ...
}


И разверните его вот таким образом:
void __buildMap(std::byte * __result_buffer) {
  auto * __result = new(__result_buffer) std::map<int, int>();
  __result->insert(42, 43);
}

void __useMap() {
  alignas(std::map<int, int>) std::byte __buildMap_result[sizeof(std::map<int, int>)];
  __buildMap(__buildMap_result);
  const auto & someDictionary = std::start_lifetime_as<const std::map<int, int>>(__buildMap_result);
  ...
}


И?

Какие проблемы с UB?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.