Параметр функции есть lvalue. В данном контексте речь — об этом.
То, что компилятор имеет право "жульничать" в целях оптимизации, пока программист не видит, то есть, не берёт адрес от объекта, не означает, что у объектов lvalue нет адреса.
Не могу придумать случай, когда нужно отличать меджу собой пустые объекты. Если задумка в том, чтобы создавать пустые объекты в куче и их адреса использовать как уникальные идентификаторы,
Нет, всё проще.
Например, может быть уже написан шаблонный код, который использует технику пробега по массиву указателями, который работает для всех типов, кроме предлагаемого вами void.
Или используется range-based for для массивов.
Получается, неразличимость объектов по адресам ломает обратную совместимость.
Скажем, так: вы опоздали с этим предложением, потому что огромное количество подобного кода уже написано.
Кстати, используя расширения компиляторов, можно посмотреть, как всё будет выглядеть:
В плюсы пока не завезли методы для простых типов, так что с этой стороны они пока ещё не объекты. Или можно писать (42).to_string(), я что-то пропустил?
Я о другом, — в обратную сторону. Что это за this такой в методах, откуда он там берётся?
Для пустых объектов без разницы, на каком экземпляре вызывать метод, метод не может работать с данными объекта, поэтому совпадение адресов не ломает ничего.
А если метод возвращает адрес объекта?
Объект характеризуется не только данными, но и адресом данных.
Вот если бы ещё и с адресами нельзя было работать...
В чём опасность, если обращение к void - это no-op?
Если no-op, тогда — другое дело.
Но это не отменяет проблем с неразличимостью адресов.
В си различаются простые типы (int, char) и составные (struct, class).
Статья — по C++.
У void нет методов - нет проблем.
Вы — в курсе, что методы — это синтаксический сахар, и на самом деле вызывается функция, которой первым параметром передаётся ссылка на объект?
Если представить объект, состоящий из void-ов, то у объекта нет состояния, значит и поведение всех экземпляров одинаковое.
У объектов пустого класса тоже нет состояния, и — что?
Тут нужны примеры, где это могло встретиться в реальном коде.
Для примеров необходимо отдельно исследовать вопрос, чтобы найти что-то менее тривиальное.
Пока всё довольно бесполезное и потенциально опасное, например, станут возможны ссылки на void, поскольку теперь можно будет разыменовать указатель на void, но эти к этим ссылкам нельзя будет обращаться.
Так вы за веткой не следите. Я начал этот холивар, чтобы унифицировать void-функции и функции со значением. Чтобы например при кодогенерации не делать 2 обёртки типа
Как видите, для получения универсального варианта нет необходимости в том, чтобы void стал "обычным" типом.
Да вроде никто не отбирает эту возможность, всё что раньше работало - продолжит работать.
Если адреса различных объектов типа void могут быть равны, а это именно так и будет, если его размер сделать равным 0, то возможности различать объекты типа void по адресам не будет.
При этом неявном приведении "вложенность" указателя не имеет значения, поэтому можно написать такой код:
int main(void) {
void *p = &p;
printf("%p\n", p);
Выражение &p имеет тип указатель на указатель на void, но поскольку указатель на любой тип данных, даже если этот тип данных сам по себе указатель, неявно приводится к указателю на void, то это происходит и в данном случае.
Это относится только к указателям на данные, поэтому указатель на функцию нельзя привести к указателю на void, точнее, можно, но это -- UB.
Одной из причин может быть то, что размер указателя на функцию может быть больше размера указателя на данные.
А адреса &s и &s.v0 будут одинаковыми, но снова очевидно, что это разные объекты.
Адреса массива и его первого элемента тоже совпадают.
s.v0 — подобъект объекта s, здесь нет ничего удивительного. Добавьте ещё оно поле ненулевого размера перед полем v0, и тогда адреса s и s.v0 перестанут совпадать.
К обсуждаемому это не относится.
И что?
Речь шла о том, один ли объект нулевого размера, или их может быть несколько.
Вы утверждали, что — один, я показываю, что их может быть несколько.
Для начала надо бы понять, зачем нам вообще различать объекты по адресам. Что это дает?
Например, можно защититься от присваивания самому себе. Если этого — мало, можно почитать эту ветку на SO.
Если сами объекты неразличимы, то зачем требовать, чтобы их адреса различались?
Для начала ответьте на вопросы:
Какие операции уместны для типа с нулевым размером, кроме взятия адреса и операции "запятая"?
и
Какова "польза" от наличия такого типа?
А то вы обсуждаете, как должен быть введён этот тип, забыв обдумать, а — нужен ли он такой вообще?
Абсолютных аргументов здесь и нет, это — вопрос выбора.
В расте, например, такой код будет работать по-разному будучи собранным в дебаге и релизе, но это никого из апологетов раста не смущает, все привыкли, дескать, "а чего вы хотите от объектов с нулевым размером", как в анекдоте про доктора, который отвечает пациенту "а вы так не делайте".
Так объект нулевого размера всегда один, что там различать?
Это он в одном и том же массиве — "один".
А, например, в такой структуре:
struct {
void v0;
char c;
void v1;
} s;
Адреса &s.v0 и &s.v1, очевидно, будут различными, и это будут разные объекты.
Операции -- ну, вот в том же Rust какие-то операции нашлись?
Rust — это Rust, а здесь — C++.
Так какие операции уместны для типа с нулевым размером, кроме взятия адреса и операции "запятая" (которая, кстати, и сейчас работает для выражений типа void)?
Какова "польза" от наличия такого типа?
Перевешивает ли она вред от потери возможности различать объекты по адресам?
Это просто следствие того, что потребовали, что каждый элемент массива должен иметь свой адрес. Чем это требование обосновано?
Как минимум тем, что иначе, как я написал выше, будет невозможно различать различные объекты по адресам.
Видимо, пока его писали, просто забыли, что элемент может иметь нулевой размер, автоматических решалок-то ограничений еще не было, никто противоречивость и не заметил
Сомневаюсь, что забыли и не заметили.
Если вернуться к основам, то тип характеризуется набором операций, определённых над объектами этого типа, а если это ещё и тип данных, то — и размером.
С размером — всё понятно, он равен 0. Какие операции были бы уместны для объектов такого типа?
Для различения объектов при доступе к ним через указатели.
Вообще, первая же найденная мной ссылка по данному вопросу описывает несколько вариантов, в которых возникли бы проблемы, если бы тип был нулевого размера.
Нужно объяснять. Потому что все считают это очевидным, а как сформулировать словами, так впадают в ступор.
В ступор впадают не все.
Адрес следующего элемента в массиве отличается от адреса текущего на размер элемента. Если размер элемента равен 0, то адреса всех элементов в массиве будут иметь один и тот же адрес, и их невозможно будет различить по адресам.
В C void - это, как там, "incomplete type that cannot be complete" или как-то так, поэтому его размер неизвестен и известен быть не может, какая уж тут адресная арифметика.
Верно, но речь-то о том, что (я отвечал на эту цитату):
Сделать sizeof(void) == 0 и всё.
После этого препятствий для самой адресной арифметики нет.
Сделать sizeof(void) == 0 и всё. Компилятор не пришлось бы усложнять, void-значение занимало бы 0 места в распределении регистров при передаче параметров или возврате результата.
Каждый элемент массива, в том числе, из void'ов, должен иметь уникальный адрес.
С адресной арифметикой знакомы? Можно дальше не объяснять?
Именно такова причина, по которой размер типа данных не может быть равен 0.
Наоборот. Те кту будут упорно искать то что не существует, останутся позади тех кто будет искать то что существует.
Примерно как средневековые ученые, которые искали бога и разумный замысел во всем в то время как надо было тупо записать уравненения.
Зачем искать то, чего не существует?
Слово "искать" здесь — неточное: уточнять свойства и понимать, каковы возможности и пределы.
Здесь лишнее слово "интеллект". "Интеллект" это то как то что я делаю выглядит изнури моего разума. А нужно оперировать вещами которые мы рассматриваем снаружи.
Однако, несмотря на разницу изнутри и снаружи, логично воспользоваться пониманием, идущим изнутри, что интеллект — это не просто хитро накрученная интуиция.
Возможно, снаружи интеллект и будет выглядеть неожиданно, но, в любом случае, он будет кардинально отличаться от интуиции.
Точно не они. Нужно просто найти способ обучения, который позволить научить сеть-агента, которая активно планирует действия для удовлетворения мотиваций.
А если это принципиально невозможно в рамках данной архитектуры, как невозможно найти точку пересечения параллельных прямых?
Чем все и занимаются вроде.
Вот и плохо, пора бы уже делом заняться, а не поиском точки пересечения параллельных прямых.
Суть здесь в том, что и первые и вторые вещи искать никогда не пора.
Те, кто упорно не будет искать того, что уже можно, просто останутся позади тех, кто будет.
Правда, слово "искать" здесь неточное, скорее, уточнять свойства и понимать, каковы возможности и пределы.
По той причине что они не существуют как некие качества или объекты, которые можно выделить и изучать.
Посылка для этого вывода — какая-то несерьёзная.
Существует только набор оъективных оценок - какого рода задачи AI уже может решать а какого еще нет. А так же существует понимание механизмов как эти задачи решаются.
Чтобы сделать оценки, необходимо понимание свойств механизмов и идентификация самих механизмов, но вы говорите, что их искать никогда не пора.
Если есть понимание, что архитектура LLM в принципе неспособна на интеллект, то усилия сосредотачиваются в попытках найти другую архитектуру, которая могла бы реализовывать интеллект.
Если нет — усилия сосредотачиваются на усовершенствовании LLM, что, очевидно, в силу свойств LLM, не приведёт к появлению интеллекта, и поэтому его создание отсрочивается на неопределённое время.
Я думаю, что следует подождать, когда рано или поздно осуществится следующий прорыв, как он осуществился уже с LLM, но только уже в сторону настоящего интеллекта.
Тогда и будет понятно, пора было те вещи искать или нет.
Если прорыв осуществят именно те, кто искали, нашли и воспользовались найденным, то значит, было пора.
Параметр функции есть lvalue.
В данном контексте речь — об этом.
То, что компилятор имеет право "жульничать" в целях оптимизации, пока программист не видит, то есть, не берёт адрес от объекта, не означает, что у объектов lvalue нет адреса.
Нет, всё проще.
Например, может быть уже написан шаблонный код, который использует технику пробега по массиву указателями, который работает для всех типов, кроме предлагаемого вами
void
.Или используется range-based
for
для массивов.Получается, неразличимость объектов по адресам ломает обратную совместимость.
Скажем, так: вы опоздали с этим предложением, потому что огромное количество подобного кода уже написано.
Кстати, используя расширения компиляторов, можно посмотреть, как всё будет выглядеть:
Видите, Loop 1 не отработал для
void0
?Обратная совместимость.
ЗЫ. Используя это расширение, вы вполне можете попробовать реально поэкспериментировать со своим вариантом типа
void
.ЗЗЫ. Интересно, что часть компиляторов, кроме gcc, могут выделить максимальное возможное количество элементов:
а gcc — не может даже такой:
Пишет:
Понимаете, 0 превышает максимальный размер объекта 9223372036854775807.
Какой у них огромный 0...
Я о другом, — в обратную сторону.
Что это за
this
такой в методах, откуда он там берётся?А если метод возвращает адрес объекта?
Объект характеризуется не только данными, но и адресом данных.
Вот если бы ещё и с адресами нельзя было работать...
Если no-op, тогда — другое дело.
Но это не отменяет проблем с неразличимостью адресов.
Никакого предупреждения не может быть по поводу неявного приведения указателя на тип данных к указателю на
void
и обратно.Если вы не учитываете константность при приведении, то могут быть предупреждения, но к самому этому неявному приведению они не относятся.
Это снижает читабельность, замусоривая код.
Статья — по C++.
Вы — в курсе, что методы — это синтаксический сахар, и на самом деле вызывается функция, которой первым параметром передаётся ссылка на объект?
У объектов пустого класса тоже нет состояния, и — что?
Для примеров необходимо отдельно исследовать вопрос, чтобы найти что-то менее тривиальное.
Пока всё довольно бесполезное и потенциально опасное, например, станут возможны ссылки на
void
, поскольку теперь можно будет разыменовать указатель наvoid
, но эти к этим ссылкам нельзя будет обращаться.Это и сейчас возможно.
Передать
void
в функцию нельзя, поэтому в таком случае не получится.А вот в этом случае — всё получится, можно упростить:
Так в статье же это описано.
Но зато проблемы будут с новым.
То есть, сам по себе тип — бесполезен.
А для чего здесь искусственная промежуточная переменная
r
?Вот — другой, универсальный вариант, работающий и для
void
'а:Так — нельзя?
Как видите, для получения универсального варианта нет необходимости в том, чтобы
void
стал "обычным" типом.Если адреса различных объектов типа
void
могут быть равны, а это именно так и будет, если его размер сделать равным 0, то возможности различать объекты типаvoid
по адресам не будет.А что это тогда?
Они в принципе не могут всегда быть одним экземпляром, пример я приводил здесь.
Следствием является то, что адреса всех элементов в массиве становятся равны и поэтому не различимы по адресу.
По той ссылке, которую я раньше приводил, есть ещё примеры проблем, возникающих из-за одинаковости адресов различных объектов.
Если заменить на
char
, то ничего не изменится:В C имеется неявное приведение указателя на любой тип данных к указателю на
void
и обратно, поэтому сvoid
'ом должно выглядеть так:При этом неявном приведении "вложенность" указателя не имеет значения, поэтому можно написать такой код:
Выражение
&p
имеет тип указатель на указатель наvoid
, но поскольку указатель на любой тип данных, даже если этот тип данных сам по себе указатель, неявно приводится к указателю наvoid
, то это происходит и в данном случае.Это относится только к указателям на данные, поэтому указатель на функцию нельзя привести к указателю на
void
, точнее, можно, но это -- UB.Одной из причин может быть то, что размер указателя на функцию может быть больше размера указателя на данные.
Адреса массива и его первого элемента тоже совпадают.
s.v0
— подобъект объектаs
, здесь нет ничего удивительного.Добавьте ещё оно поле ненулевого размера перед полем
v0
, и тогда адресаs
иs.v0
перестанут совпадать.К обсуждаемому это не относится.
Речь шла о том, один ли объект нулевого размера, или их может быть несколько.
Вы утверждали, что — один, я показываю, что их может быть несколько.
Например, можно защититься от присваивания самому себе.
Если этого — мало, можно почитать эту ветку на SO.
Для начала ответьте на вопросы:
и
А то вы обсуждаете, как должен быть введён этот тип, забыв обдумать, а — нужен ли он такой вообще?
Абсолютных аргументов здесь и нет, это — вопрос выбора.
Что характеризует выбор, сделанный в Rust'е.
Однако, так — нечестно, так и в C/C++ адреса разные будут.
Вот так — куда честнее.
Первый раз писал на Rust'е, и больше не хочу. Компилятор мне ещё указывает, в каком регистре идентификаторы заводить.
Отлично, ребята сделали себе игрушку, но почему им теперь обязательно нужно "осчастливливать" таким же выбором C/C++?
Апологеты C/C++, почему-то не пытаются осчастливливать Rust.
Это он в одном и том же массиве — "один".
А, например, в такой структуре:
Адреса
&s.v0
и&s.v1
, очевидно, будут различными, и это будут разные объекты.Rust — это Rust, а здесь — C++.
Так какие операции уместны для типа с нулевым размером, кроме взятия адреса и операции "запятая" (которая, кстати, и сейчас работает для выражений типа
void
)?Какова "польза" от наличия такого типа?
Перевешивает ли она вред от потери возможности различать объекты по адресам?
Как минимум тем, что иначе, как я написал выше, будет невозможно различать различные объекты по адресам.
Сомневаюсь, что забыли и не заметили.
Если вернуться к основам, то тип характеризуется набором операций, определённых над объектами этого типа, а если это ещё и тип данных, то — и размером.
С размером — всё понятно, он равен 0.
Какие операции были бы уместны для объектов такого типа?
Для различения объектов при доступе к ним через указатели.
Вообще, первая же найденная мной ссылка по данному вопросу описывает несколько вариантов, в которых возникли бы проблемы, если бы тип был нулевого размера.
В ступор впадают не все.
Адрес следующего элемента в массиве отличается от адреса текущего на размер элемента. Если размер элемента равен 0, то адреса всех элементов в массиве будут иметь один и тот же адрес, и их невозможно будет различить по адресам.
Верно, но речь-то о том, что (я отвечал на эту цитату):
После этого препятствий для самой адресной арифметики нет.
Каждый элемент массива, в том числе, из
void
'ов, должен иметь уникальный адрес.С адресной арифметикой знакомы?
Можно дальше не объяснять?
Именно такова причина, по которой размер типа данных не может быть равен 0.
Зачем искать то, чего не существует?
Слово "искать" здесь — неточное: уточнять свойства и понимать, каковы возможности и пределы.
Однако, несмотря на разницу изнутри и снаружи, логично воспользоваться пониманием, идущим изнутри, что интеллект — это не просто хитро накрученная интуиция.
Возможно, снаружи интеллект и будет выглядеть неожиданно, но, в любом случае, он будет кардинально отличаться от интуиции.
А если это принципиально невозможно в рамках данной архитектуры, как невозможно найти точку пересечения параллельных прямых?
Вот и плохо, пора бы уже делом заняться, а не поиском точки пересечения параллельных прямых.
Те, кто упорно не будет искать того, что уже можно, просто останутся позади тех, кто будет.
Правда, слово "искать" здесь неточное, скорее, уточнять свойства и понимать, каковы возможности и пределы.
Посылка для этого вывода — какая-то несерьёзная.
Чтобы сделать оценки, необходимо понимание свойств механизмов и идентификация самих механизмов, но вы говорите, что их искать никогда не пора.
Если есть понимание, что архитектура LLM в принципе неспособна на интеллект, то усилия сосредотачиваются в попытках найти другую архитектуру, которая могла бы реализовывать интеллект.
Если нет — усилия сосредотачиваются на усовершенствовании LLM, что, очевидно, в силу свойств LLM, не приведёт к появлению интеллекта, и поэтому его создание отсрочивается на неопределённое время.
Я думаю, что следует подождать, когда рано или поздно осуществится следующий прорыв, как он осуществился уже с LLM, но только уже в сторону настоящего интеллекта.
Тогда и будет понятно, пора было те вещи искать или нет.
Если прорыв осуществят именно те, кто искали, нашли и воспользовались найденным, то значит, было пора.
Но, тем не менее, компьютеры умеют что-то ещё, помимо 0 и 1.
Алгоритмам — все равно, на основе чего работать, они — нематериальны.
Ощущения (квалиа), сознание и душу пока, действительно, рановато искать, а вот интуицию и интеллект — уже пора.
Без этого всё будет намного дольше и труднее, и будет в куда более значительной степени зависеть от удачи.