И всё‑таки на вопрос «У мамы Натали четверо детей: Саша, Маша, Коля и Никита. Сколько у неё дочек?» мне ответы от нейронок так пока никто и не показал.
В самих структурах должны быть не указатели на функции интерфейса, а указатели на служебные структуры, в свою очередь, содержащие уже указатели на сами функции интерфейса.
Тогда, сколько бы не было функций у интерфейса, в каждом экземпляре память расходовалась бы только на указатель на служебную структуру.
А сейчас, если имеется, к примеру, 50 функций в интерфейсе, то каждый экземпляр вынужден хранить все 50 указателей на эти функции.
Ну, и фразы, вроде того, что в C имеются структуры с функциями, конечно, дискредитируют.
Вообще говоря это не однозначная с точки зрения синтаксиса конструкция т.к. это может быть и выражение инициализации рвалью войд (или ещё по другому это можно считать войд литералом) так и сигнатурой функции которая ничего не принимает и ничего не возвращает.
Верно.
Единственное что могу предположить, что токены внутри деклвал трактуются как выражение == инициализация, а не как тип.
Да, всё верно, и косвенно это можно увидеть из сообщений об ошибках компиляторов.
using fun = void();
using x = decltype(void());
using y = decltype(fun);
using z = decltype(void (*)());
генерируются типичные сообщения об ошибках:
<source>:4:20: error: unexpected type name 'fun': expected expression
4 | using y = decltype(fun);
| ^
<source>:5:27: error: expected expression
5 | using z = decltype(void (*)());
| ^
2 errors generated.
или:
<source>(4): error C3553: decltype expects an expression not a type
<source>(5): error C2760: syntax error: ')' was unexpected here; expected 'expression'
<source>(5): error C2059: syntax error: ')'
<source>(5): error C2059: syntax error: ')'
<source>(5): error C2059: syntax error: ')'
Для 3-ей строки никакой ошибки не сгенерировано.
А в сгенерированных сообщениях об ошибках прямо и недвусмысленно указано: "expected expression" и даже ещё более доходчиво: "decltype expects an expression not a type".
Да, не понимаю. Вы «исправили» мой код, заменив {} на (), а потом приводите ссылку на Стандарт, говорящий, что «{} или () приводит к такому-то результату» (подразумевая, что разницы нет). И я вот не понимаю: вас здесь ничего не смущает?
Меня — нет, не смущает.
По Стандарту разницы — нет, но clang — глючит, и поэтому при его использовании разница появляется.
Я вам это уже не первый раз объясняю, а вы всё понять не можете.
Именно, не одно и то же (в данном контексте).
Не часто удаётся встретить человека, спорящего со Стандартом.
Правда, ещё непонятно, зачем вы «исправили» мой код на (),
Чтобы clang перестал глючить и заработал согласно Стандарта.
Причём тут оправдывания? Это ровно тот сорт специальных случаев и исключений, про которые я говорил в самом начале.
При том, что это именно вы утверждали про меня:
Пока что вы показываете полное незнание языка
однако, на поверку, не я, а вы это показываете.
А теперь ещё и спорите со Стандартом.
И, кстати, что же вы тут имели в виду под инстанцированием?
Очевидно, создание объектов.
Так код уже сломан на практике. Он в разных компиляторах и в разное время показывает разные результаты.
На данный момент сломан clang, а не код, но вам, похоже, — все равно, ведь вам ваши хотелки важнее.
Мы ведь оба понимаем, что это не так? Шаблонную функцию, написанную заранее и давно, которая принимает тип T с полями foo и bar и ожидает, что у них разные адреса, и которая сломается от типа с такой аннотацией, вы можете себе представить?
У меня написано:
Если кто-то сознательно хочет нарушить уникальность адресов ради экономии памяти, зная, что в этом месте ему эта уникальность не нужна
Вы не заметили мою фразу "зная, что в этом месте ему эта уникальность не нужна", верно?
Если тип T с полями foo и bar передаётся в шаблонную функцию, которая ожидает, что у них разные адреса, то это ведь — не тот случай, для которого верно условие "зная, что в этом месте ему эта уникальность не нужна"?
И — не важно, прямо эта уникальность ожидается или косвенно, посредством давно написанной шаблонной функции.
Я вам ссылку на Стандарт привёл и даже процитировал. Похоже, вы на самом деле до сих пор не понимаете, в чём дело.
И статистика по тому, какие круги широкие, а какие — узкие, у вас… откуда?
Можете считать, как хотите.
Я всего лишь задаю вам наводящие вопросы.
Наверное, уже нет необходимости.
Прощу прощенья за то, что у меня пропущена частица «не», что, впрочем, должно было быть очевидно из противопоставления «если вы считаете, что void() что-то там инициализирует, а void{} — нет».
Никакого противоречия не вижу.
Хорошо, первая часть фразы:
Пока что вы показываете полное незнание языка, если для вас void() и void{} одно и то же
Не одно и то же? Или опять частица «не» оказалась пропущенной?
А что до второго пункта — как считаете, какая часть практикующих программистов (ну, чтобы круги широкие были) знает про эту особенность?
Ну, вот, начались оправдывания...
Так что, есть у меня знания языка или нет? Или я демонстрирую полное его незнание, как вы пишете?
А может, всё-таки здесь кто-то другой чего-то не знает?
Пример работает ровно так, как задумывалось: он показывает, что поведение с void неконсистентно между разными компиляторами уже сейчас, поэтому закладываться на него нельзя.
Нет, вы считали, что clang работает правильно, а gcc — нет:
Забавно, что gcc вполне себе жрёт typename = decltype(void{}) , и то, что всех это на практике устраивает, как бы намекает нам, что всем пофиг.
Однако, — как раз, наоборот, gcc работает правильно, а clang — неправильно.
Какое-то время назад неправильно работал и gcc, и MSVC.
Во всех основных компиляторах, кроме clang'а, это исправили, думаю, в скором времени, и в clang'е исправят.
И ещё, вы писали:
Ох лол, я сконструировал такой пример
Пример имелся ввиду такой:
боюсь, что уже имеется очень много шаблонного кода, который опирается на то, что void — incomplete-тип (не инстанцируемый), и этот код сломается
Это — по поводу того, как он задумывался.
Что значит «невалидный тип»?
Я же вам привёл пример с void &.
Моя вторая доработка вашего примера работает как раз на основе него.
Вы по-видимому интерпретируете «запрет» как «явно написали, что конкретно так делать нельзя». Это слишком узкая трактовка, особенно в случае разных стандартов и прочих логических систем.
Посмотрите значение слова "запретить" в толковом словаре, например, здесь.
…в рамках вашей слишком узкой трактовки это высказывание имеет смысл, в рамках «запрещено всё, чья невозможность логически следует из стандарта» — смысла в нём нет.
Это — не моя трактовка, просто таково значение этого слова.
Проблема возникает, когда такую функцию (которая делает не связанные напрямую с совпадением адресов вещи) вы написали, а не когда её вызвали. Зачем вы пишете изначально сломанный код?
Разве я один пишу весь код в мире?
Напишут и вас не спросят. Именно поэтому вопросы "зачем" в это контексте не имеют смысла.
Расскажите это принявшим [[no_unique_address]], а то они не знают, наверное.
Знают, но по краю ходят.
Во-первых, это касается очень узкого круга случаев. Во-вторых, это надо сознательно включить, то есть, сознательно вписать этот атрибут.
Если кто-то сознательно хочет нарушить уникальность адресов ради экономии памяти, зная, что в этом месте ему эта уникальность не нужна, то — вот, он получил "ручку" для того, чтобы это сделать.
На ранее написанный код это, в принципе, повлиять не может.
А, то есть, вы себе это не представляете, но про большинство сказали? Лол.
Так это же вы предлагали дать ссылку, а не я.
Один "лол" у вас уже был, правда, вы так и не поняли в тот раз, что это был за "лол".
Я в курсе, что был Matt Calabrese, которому я лично написал емейл с вопросом о его пропозале по regular void, и который сказал, что у него руки не доходят приехать на заседание Комитета представить свой пропозал. Если на заседании Комитета пропозал никто не представляет, то его не рассматривают изначально, и о «не прошли» (и о мнении большинства) тут говорить вообще нельзя.
Очевидно, большинство не очень хочет такое предлагать, энтузиазма не видно.
Но я и в этом не вижу глубокой проблемы, потому что по факту подобные изменения никого не останавливали: в C++20 завезли (P0960) инициализирование агрегатов из скобочек, и те шаблоны, которые раньше опирались на не-well-formedness выражений T(a, b, c) теперь будут работать неправильно для некоторых T. И ничего, людей это не смущает.
Да, нехорошо получилось.
Однако, это касается довольно узкого круга случаев, к тому же, появляется некая унификация.
В случае же с void круг случаев значительно шире.
Нет, не кажется. Что такое void() и чем это отличается от void{}?
Значит, самостоятельно вы не смогли разобраться?
Пока что вы показываете полное незнание языка, если для вас void() и void{} одно и то же, и если вы считаете, что void() что-то там инициализирует, а void{} — нет.
Otherwise, if the type is cv void and the initializer is () or {} (after pack expansion, if any), the expression is a prvalue of the specified type that performs no initialization.
Так одно ли и то же void() и void{} теперь, после приведения мной цитаты из Стандарта?
Если уж и говорить о полном незнании языка, то его показываете именно вы: предложили пример, который работает не так, как вы задумывали, и вы до сих пор этого не видите, не говоря уже о том, что не понимаете сопутствующей проблемы в этом месте у компилятора clang.
Вы оказались не способны разобраться в причине, по которой clang отбрасывает первую шаблонную функцию, хотя я вам дважды намекал и говорил, что у других компиляторов тоже такая проблема была, но потом её исправили.
На godbolt'е же это легко проверить, "пощёлкав" версиями компиляторов.
У меня есть проверка возможности инстанциирования.
Вы применяете термин не по назначению, инстанцирование — это о другом. Видимо, поэтому у вас наблюдаются трудности с этим примером.
Вы определяете тип prvalue expression, а не создаёте временный объект.
И если prvalue expression — валидно, то разве у него может быть невалидый тип?
В одном из своих вариантов я доработал ваш пример так, чтобы невалидный тип (void &) возникал, когда требуется.
И ваш пример стал работать так, как вы задумывали.
На всех компиляторах.
Так в чём суть? Что делает void{}?
Надеюсь, теперь вам это понятно.
А также, что вам понятно, кто из нас здесь показывает "полное незнание языка".
Если где-то и написан осмысленный код на std::is_constructible<void> то только из-за того, что void-случаи требуют отдельной реализации (как в данной статье). Сам код вероятно не сломается, потому что пойдёт по ветке T - полноценный тип, в том числе и для void. В этом и цель предложения - убрать избыточность/копипасту.
А если void использовался как placeholder для incomplete типа, и взят был именно void, чтобы он случайно не мог быть доопределён и поэтому не мог бы стать complete-типом?
Решения, базирующиеся на этом, сломаются, если void сделать complete-типом.
Очень много. Нигде нет умножения на sizeof(char) в конструкциях типа
То есть, очень мало, а не очень много: практически никто не считает, что это может измениться.
Вот и с void'ом — так же: никто не считает, что void может стать complete-типом.
Вы понимаете практическую пользу от кода, который был вами приведён как пример "поломки"?
Не весь код в мире пишу я: есть ещё очень много других людей, которые тоже пишут код.
И понимать они практическую пользу могут очень по-своему.
По этой причине все вопросы вида "зачем так писать" и похожие по смыслу, например, о понимании практической пользы, бессмысленны.
Вот вам наглядный пример, который показывает, благодаря наличию соответствующего расширения в компиляторах, что он не может быть один.
В первом массиве объекты void неразличимы по адресам, что видно по распечатке их одинаковых адресов, и можно считать, что объект — один.
Во втором массиве их адреса уже различаются, потому что объекты находятся в составе структуры, в которой есть ещё поля с ненулевым размером, поэтому — уже не один.
Да, логично, и некоторые компиляторы, поддерживающие соответствующее расширение, даже пишут об этом в предупреждении:
<source>:12:22: warning: subtraction of pointers to type 'void0' of zero size has undefined behavior [-Wpointer-arith] 12 | ptrdiff_t delta = p2-p1; // UB?
Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above.
Видите, строковый литерал вычисляется (Evaluating a string-literal), потому что это — выражение, а не объект.
А вот вычисление этого выражения уже даёт объект (results in a string literal object).
И — далее, там же:
Whether all string-literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified.
Прямейшим текстом ещё раз написано, что строковые литералы именно вычисляются (successive evaluations of a string-literal), и что не специфицировано, дают ли последовательные вычисления строкового литерала один и тот же объект или нет (yield the same or a different object is unspecified).
Соответственно, из того, что строковые литералы при их последовательном их вычислении могут давать один и тот же объект, не следует, что адреса разных объектов могут быть равны.
И сравнение их через сравнение указателей может работать а может нет.
Верно, но, как видите, это — отнюдь не потому, что адреса разных объектов могут быть равны, а потому что строковые литералы при их вычислении могут давать один и тот же объект.
И проблема не в компиляторе, когда он сворачивает или нет константы, а в программисте, который полагается на свою логику а не факты
Верно, факты я вам привёл.
Проблема же, как вы говорите, — в программисте, который полагается на свою логику, а не на факты, и который думает, что разные объекты могут в некоторых случаях иметь один и то же адрес.
И невозможность их соблюсти означает, что запрет есть.
Совершенно не означает.
Через реку нет моста, человек может переплыть, а машина пересечь реку не может.
Означает ли это, что для машин есть запрет на пересечение реки в этом месте?
Думаю, сами понимаете абсурдность такой трактовки.
Если построить мост, то для машин появится возможность пересечь реку в данном месте, но это не означает, что для машин был снят запрет на это пересечение.
Потому что запрета и не было, была другая причина наблюдаемого не пересечения машинами реки до постройки моста.
Думаю, к этой части больше возвращаться не потребуется.
Значит, какая разница в наблюдаемом поведении?
Никакой.
Не понял, как отсутствие наблюдаемых изменений от явного добавления запрета говорит о том, что сейчас запрета нет?
А почему отсутствие наблюдаемых изменений должно говорить о наличии или отсутствии именно запрета, если возможны другие причины, кроме запрета?
Я выше привёл пример с мостом через реку, который это объясняет.
про самоприсваивание вы слились вспомнили про шаблонные функции и в ответ на просьбу привести пример сказали «очень смешно».
Я не поддался на провокацию. Что тут приводить?
Какая другая потребность различать объекты типа void у вас осталась?
Если шаблонная функция перед присваиванием проверяет, не самоприсваивание ли это, путём сравнения адресов, то, будучи инстанцированной для типа void, в некоторых случаях для разных объектов void она будет считать, что самоприсваивание есть, а в некоторых, — что его нет.
Если при этом, в случае, как она считает, отсутствия самоприсваивания, она выполняет дополнительные вещи, которые важны, то вот здесь и возникает проблема.
Это — то, что первое пришло в голову, то есть, могут быть и более "впечатляющие" случаи, но уже одного этого достаточно.
Такую фундаментальную вещь, как уникальность адреса для объектов любых типов, трогать нельзя.
Она настолько фундаментальная, что верна даже для функций.
Можно ссылку на это большинство?
Как вы себе это представляете?
Есть куда более сильная вещь, чем ссылка, — реальность.
Вы — в курсе, что предложения подобного рода уже были, и они не прошли?
Ответ ChatGPT.
Это — вообще не вопрос.
Современному ИИ нечем знать, нет у него такого "Органа", которым можно было бы знать.
В №1 забыли написать:
Такое даже на голом C можно написать, только
std::size
необходимо заменить на соответствующее.То есть, механизм-то — есть, но его не применяют.
Когда они правильно расшифруют, что значит буква I в их AGI, тогда у них появится шанс.
Это — не ключевое слово:
Видите, какое хулиганство?
А всё — потому, что
final
— не ключевое слово.И ― что?
Возврат-то все равно идёт по значению.
Другое дело, что в таком коде логично использовать составной литерал:
Статья дискредитирует немного по другой причине.
В самих структурах должны быть не указатели на функции интерфейса, а указатели на служебные структуры, в свою очередь, содержащие уже указатели на сами функции интерфейса.
Тогда, сколько бы не было функций у интерфейса, в каждом экземпляре память расходовалась бы только на указатель на служебную структуру.
А сейчас, если имеется, к примеру, 50 функций в интерфейсе, то каждый экземпляр вынужден хранить все 50 указателей на эти функции.
Ну, и фразы, вроде того, что в C имеются структуры с функциями, конечно, дискредитируют.
Он, видимо, уже знал, что следить могут только через цветной телевизор.
Чёрно-белый для этого не годится.
Верно.
Да, всё верно, и косвенно это можно увидеть из сообщений об ошибках компиляторов.
Для данного примера:
генерируются типичные сообщения об ошибках:
или:
Для 3-ей строки никакой ошибки не сгенерировано.
А в сгенерированных сообщениях об ошибках прямо и недвусмысленно указано: "expected expression" и даже ещё более доходчиво: "decltype expects an expression not a type".
Точнее, реальное применение.
Но здесь это — необязательно.
Да, верно.
Писатели очень изобретательны, они и без меня изобретут множество смыслов и применений.
Мне же здесь достаточно показать механизм, который они будут использовать для своих изобретений, которые сломаются, если
void
сделать complete-типом.Меня — нет, не смущает.
По Стандарту разницы — нет, но clang — глючит, и поэтому при его использовании разница появляется.
Я вам это уже не первый раз объясняю, а вы всё понять не можете.
Не часто удаётся встретить человека, спорящего со Стандартом.
Чтобы clang перестал глючить и заработал согласно Стандарта.
При том, что это именно вы утверждали про меня:
однако, на поверку, не я, а вы это показываете.
А теперь ещё и спорите со Стандартом.
Очевидно, создание объектов.
На данный момент сломан clang, а не код, но вам, похоже, — все равно, ведь вам ваши хотелки важнее.
У меня написано:
Вы не заметили мою фразу "зная, что в этом месте ему эта уникальность не нужна", верно?
Если тип
T
с полямиfoo
иbar
передаётся в шаблонную функцию, которая ожидает, что у них разные адреса, то это ведь — не тот случай, для которого верно условие "зная, что в этом месте ему эта уникальность не нужна"?И — не важно, прямо эта уникальность ожидается или косвенно, посредством давно написанной шаблонной функции.
Я вам ссылку на Стандарт привёл и даже процитировал.
Похоже, вы на самом деле до сих пор не понимаете, в чём дело.
Можете считать, как хотите.
Наверное, уже нет необходимости.
Никакого противоречия не вижу.
Хорошо, первая часть фразы:
Не одно и то же?
Или опять частица «не» оказалась пропущенной?
Ну, вот, начались оправдывания...
Так что, есть у меня знания языка или нет?
Или я демонстрирую полное его незнание, как вы пишете?
А может, всё-таки здесь кто-то другой чего-то не знает?
Нет, вы считали, что clang работает правильно, а gcc — нет:
Однако, — как раз, наоборот, gcc работает правильно, а clang — неправильно.
Какое-то время назад неправильно работал и gcc, и MSVC.
Во всех основных компиляторах, кроме clang'а, это исправили, думаю, в скором времени, и в clang'е исправят.
И ещё, вы писали:
Пример имелся ввиду такой:
Это — по поводу того, как он задумывался.
Я же вам привёл пример с
void &
.Моя вторая доработка вашего примера работает как раз на основе него.
Посмотрите значение слова "запретить" в толковом словаре, например, здесь.
Это — не моя трактовка, просто таково значение этого слова.
Разве я один пишу весь код в мире?
Напишут и вас не спросят.
Именно поэтому вопросы "зачем" в это контексте не имеют смысла.
Знают, но по краю ходят.
Во-первых, это касается очень узкого круга случаев.
Во-вторых, это надо сознательно включить, то есть, сознательно вписать этот атрибут.
Если кто-то сознательно хочет нарушить уникальность адресов ради экономии памяти, зная, что в этом месте ему эта уникальность не нужна, то — вот, он получил "ручку" для того, чтобы это сделать.
На ранее написанный код это, в принципе, повлиять не может.
Так это же вы предлагали дать ссылку, а не я.
Один "лол" у вас уже был, правда, вы так и не поняли в тот раз, что это был за "лол".
Очевидно, большинство не очень хочет такое предлагать, энтузиазма не видно.
Создаёт prvalue.
Да, нехорошо получилось.
Однако, это касается довольно узкого круга случаев, к тому же, появляется некая унификация.
В случае же с
void
круг случаев значительно шире.Значит, самостоятельно вы не смогли разобраться?
Во втором пункте этой части Стандарта написано:
Так одно ли и то же
void()
иvoid{}
теперь, после приведения мной цитаты из Стандарта?Если уж и говорить о полном незнании языка, то его показываете именно вы: предложили пример, который работает не так, как вы задумывали, и вы до сих пор этого не видите, не говоря уже о том, что не понимаете сопутствующей проблемы в этом месте у компилятора clang.
Вы оказались не способны разобраться в причине, по которой clang отбрасывает первую шаблонную функцию, хотя я вам дважды намекал и говорил, что у других компиляторов тоже такая проблема была, но потом её исправили.
На godbolt'е же это легко проверить, "пощёлкав" версиями компиляторов.
Вы применяете термин не по назначению, инстанцирование — это о другом. Видимо, поэтому у вас наблюдаются трудности с этим примером.
Вы определяете тип prvalue expression, а не создаёте временный объект.
И если prvalue expression — валидно, то разве у него может быть невалидый тип?
В одном из своих вариантов я доработал ваш пример так, чтобы невалидный тип (
void &
) возникал, когда требуется.И ваш пример стал работать так, как вы задумывали.
На всех компиляторах.
Надеюсь, теперь вам это понятно.
А также, что вам понятно, кто из нас здесь показывает "полное незнание языка".
А если
void
использовался как placeholder для incomplete типа, и взят был именноvoid
, чтобы он случайно не мог быть доопределён и поэтому не мог бы стать complete-типом?Решения, базирующиеся на этом, сломаются, если
void
сделать complete-типом.То есть, очень мало, а не очень много: практически никто не считает, что это может измениться.
Вот и с
void
'ом — так же: никто не считает, чтоvoid
может стать complete-типом.Не весь код в мире пишу я: есть ещё очень много других людей, которые тоже пишут код.
И понимать они практическую пользу могут очень по-своему.
По этой причине все вопросы вида "зачем так писать" и похожие по смыслу, например, о понимании практической пользы, бессмысленны.
Собеседник предложил код:
и сказал:
Что тогда мешает в таком же стиле изменить
sizeof(char)
?Примерно одного порядка вещи.
Я поэтому и задал этот вопрос, чтобы понятно было, насколько это нельзя менять.
Нет, я имел ввиду ровно то, что написал.
CHAR_BITS
существует ещё с древних времён C.Мало ли, что говорят.
Я же уже приводил вам пример, как так может быть.
Вот вам наглядный пример, который показывает, благодаря наличию соответствующего расширения в компиляторах, что он не может быть один.
В первом массиве объекты
void
неразличимы по адресам, что видно по распечатке их одинаковых адресов, и можно считать, что объект — один.Во втором массиве их адреса уже различаются, потому что объекты находятся в составе структуры, в которой есть ещё поля с ненулевым размером, поэтому — уже не один.
Да, логично, и некоторые компиляторы, поддерживающие соответствующее расширение, даже пишут об этом в предупреждении:
для этого кода:
Вы обнаружили ещё один прикол, который возникает в адресной арифметике, если сделать размер типа равным 0.
Ещё один аргумент против размера типа, равного 0.
А вот это — неверно.
Вы же сами приводили пример с делением: делить на 0 нельзя, но умножать-то на него, то есть, выполнять обратную операцию, — можно.
Так и здесь.
Там будет эксплуатироваться то же самое.
Ну, если суть не видна, то ничем помочь не могу.
А реальные программы рассчитаны на то, что функция начнёт возвращать другой результат?
Сколько программ рассчитано на то, что
sizeof(char)
может быть не равно 1?Здесь, примерно, — то же самое.
Очевидно, здесь имеются ввиду строковые литералы.
Вы когда-нибудь задумывались о том, что такое строковый литерал?
Вы уверены в том, что строковый литерал — это объект?
Если обратиться к первоисточнику, то можно узнать, что:
Никакой не объект, а — выражение.
И далее, первоисточник, 14-ый пункт (в самом низу):
Видите, строковый литерал вычисляется (Evaluating a string-literal), потому что это — выражение, а не объект.
А вот вычисление этого выражения уже даёт объект (results in a string literal object).
И — далее, там же:
Прямейшим текстом ещё раз написано, что строковые литералы именно вычисляются (successive evaluations of a string-literal), и что не специфицировано, дают ли последовательные вычисления строкового литерала один и тот же объект или нет (yield the same or a different object is unspecified).
Соответственно, из того, что строковые литералы при их последовательном их вычислении могут давать один и тот же объект, не следует, что адреса разных объектов могут быть равны.
Верно, но, как видите, это — отнюдь не потому, что адреса разных объектов могут быть равны, а потому что строковые литералы при их вычислении могут давать один и тот же объект.
Верно, факты я вам привёл.
Проблема же, как вы говорите, — в программисте, который полагается на свою логику, а не на факты, и который думает, что разные объекты могут в некоторых случаях иметь один и то же адрес.
Совершенно не означает.
Через реку нет моста, человек может переплыть, а машина пересечь реку не может.
Означает ли это, что для машин есть запрет на пересечение реки в этом месте?
Думаю, сами понимаете абсурдность такой трактовки.
Если построить мост, то для машин появится возможность пересечь реку в данном месте, но это не означает, что для машин был снят запрет на это пересечение.
Потому что запрета и не было, была другая причина наблюдаемого не пересечения машинами реки до постройки моста.
Думаю, к этой части больше возвращаться не потребуется.
Никакой.
А почему отсутствие наблюдаемых изменений должно говорить о наличии или отсутствии именно запрета, если возможны другие причины, кроме запрета?
Я выше привёл пример с мостом через реку, который это объясняет.
Я не поддался на провокацию.
Что тут приводить?
Если шаблонная функция перед присваиванием проверяет, не самоприсваивание ли это, путём сравнения адресов, то, будучи инстанцированной для типа
void
, в некоторых случаях для разных объектовvoid
она будет считать, что самоприсваивание есть, а в некоторых, — что его нет.Если при этом, в случае, как она считает, отсутствия самоприсваивания, она выполняет дополнительные вещи, которые важны, то вот здесь и возникает проблема.
Это — то, что первое пришло в голову, то есть, могут быть и более "впечатляющие" случаи, но уже одного этого достаточно.
Такую фундаментальную вещь, как уникальность адреса для объектов любых типов, трогать нельзя.
Она настолько фундаментальная, что верна даже для функций.
Как вы себе это представляете?
Есть куда более сильная вещь, чем ссылка, — реальность.
Вы — в курсе, что предложения подобного рода уже были, и они не прошли?
Это и говорит о том, что "большинство считает".