Здравствуйте, B0FEE664, Вы писали:
BFE>Да вы предлагаемый синтаксис видели? Он вам такой зачем?
а что в нём такого плохого?
Вот например рядом обсуждают задачу получения минимального значения из enum
template <typename E>
requires std::is_enum_v<E>
constexpr auto enum_min()
{
auto minVal = std::numeric_limits<std::underlying_type_t<E>>::max();
template for (constexpr auto e : std::meta::enumerators_of(^E)) {
const auto v = std::to_underlying([:e:]);
if (v < minVal)
minVal = v;
}
return minVal;
}
всяко лучше, чем костыли от magic_enum
Re[3]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, sergii.p, Вы писали: BFE>>Да вы предлагаемый синтаксис видели? Он вам такой зачем? SP>а что в нём такого плохого?
В примере ниже отчётливо видны проблемы синтаксиса.
Свойства объекта записываются в C++ как? Через модификатор доступа, т.е. через . или -> a.size() — размер; p->data() — данные.
Комитетчики добавили это для метаданных? Нет, они пишут сначала преобразование всего имени в метаобъект, а потом используют сишный (!) доступ к его свойствам: std::meta::enumerators_of(^E)
Они просто издеваются над языком.
Эта запись должна выглядеть так: E.entities
Далее, вот этот синтаксис [:e:] не нужен. То, что е — это метаобъект и так известно. Поэтому e.name должно давать имя, а e.value — значение.
Далее, template for не нужен. Код относящийся к рефлексии не может выполняться в рантайме, так что template тут лишний, поэтому, кстати, enum_min() должна быть consteval, а не constexpr.
В целом я бы записал этот пример так:
template <typename E>
requires std::is_enum_v<E>
consteval E.underlying_type enum_min()
{
auto minVal = E.underlying_type.max_value;
for(auto e : E.entities)
{
const auto v = e.value;
if (v < minVal)
minVal = v;
}
return minVal;
}
— всё просто и понятно. Всё , что надо сделать, это продумать названия свойств, которые есть у метаобъектов. Причём эти свойства можно вводить постепенно, добавляя от версии к версии. Для начала — просто для чтения. Это уже решило бы 80% задач.
Вместо эволюционного пути развития комитетчики задумали революцию и изобретают метаязык который год. Результат их работы станет такая монструозная химера, которую невозможно будет нормально использовать. Надеюсь они потому её и не выпускают, что понимают, какая ерунда получается. Если они продолжат в том же духе, то эти нововведения постигнет та же судьба, что и SGML.
Скрытый текст
SP>Вот например рядом обсуждают задачу получения минимального значения из enum SP>
SP>template <typename E>
SP> requires std::is_enum_v<E>
SP>constexpr auto enum_min()
SP>{
SP> auto minVal = std::numeric_limits<std::underlying_type_t<E>>::max();
SP> template for (constexpr auto e : std::meta::enumerators_of(^E)) {
SP> const auto v = std::to_underlying([:e:]);
SP> if (v < minVal)
SP> minVal = v;
SP> }
SP> return minVal;
SP>}
SP>
SP>всяко лучше, чем костыли от magic_enum
Что же касается обсуждения рядом, то я могу лишь повториться: набор констант и перечисление — это два различных "метатипа". У нормального перечисления вообще нет значений. Если вам нужны значения, значит вам нужен набор констант, а не перечисление.
И каждый день — без права на ошибку...
Re[3]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, sergii.p, Вы писали:
BFE>>Да вы предлагаемый синтаксис видели? Он вам такой зачем?
SP>а что в нём такого плохого?
Примерно всё плохо. Вместо языка запросов имеем псевдо c++. Что мешало использовать обычные строки вместо бяанов [::] ?
Нет возможности сохранить результат в файл или обратится к базе.
И потом этап синтеза кода лучше разделить, а не пихать всё в кучу умножая сложность.
Здравствуйте, ·, Вы писали:
BFE>>Эта запись должна выглядеть так: BFE>>E.entities ·>А что делать, если в E уже есть имя entities? В лучшем случае что-то вроде std::meta<E>::entities.
Ничего не делать. E.entities и E::entities — это доступ к разным значениям.
И каждый день — без права на ошибку...
Re[2]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, ботаныч, Вы писали:
Б>>прогнозы? к какому году, к примеру у мелгкомякгких появится..
BFE>Да вы предлагаемый синтаксис видели? Он вам такой зачем?
Много проще чем в велосипедах на хаках да СФИНАЯХ, сейчас хоть вариэдики появились, нет потребности в тех многопараметриальных шаблонах.
Это конечно решалось макросами с __VA_ARGS__, что легко конвертиировалось с структуры вида template <typename Before, typename Next> struct item; в бустах для этого (по памяи, могу оши баться) template <typename Before, typename Next, int Way> v_item;
Собственно появление этой фичи в стандарте может серьезно поменять позиции в usability, т.к. всякие гибернейты и прочие ком|ком+ будут создаваться влет
Re[4]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, sergii.p, Вы писали:
BFE>>>Да вы предлагаемый синтаксис видели? Он вам такой зачем? SP>>а что в нём такого плохого? BFE>В примере ниже отчётливо видны проблемы синтаксиса. BFE>Свойства объекта записываются в C++ как? Через модификатор доступа, т.е. через . или -> BFE>a.size() — размер; BFE>p->data() — данные.
операторы выше используются часто и в рантайме, в частности с виртуальными фунцкиями прочей, где и сам метод вычисляется по таблице вирт ф-ций. Не вижу причин упоминать здесь операторы -> и ., в качестве претензий .., получить от рефлекшина вариэдик из &class__::mem; а для этого предложенный синтаксис вполне удовлетворителен.
BFE>Комитетчики добавили это для метаданных? Нет, они пишут сначала преобразование всего имени в метаобъект, а потом используют сишный (!) доступ к его свойствам:
сишный доступ для компайлтайм звучит как прокрутить фарш обратно
BFE>Эта запись должна выглядеть так: BFE>E.entities
Шарпофщина какая-то, это там к "вложенным типам" обращаются через точку, в плюсах привычнее с::m
BFE>Далее, вот этот синтаксис [:e:] не нужен. То, что е — это метаобъект и так известно. Поэтому e.name должно давать имя, а e.value — значение.
я сомневаюсь, что без наличия под рукой текущий компилятор с тем, чтобы ззаранее проверить какие синтаксические нагрузки надо добавить, что-бы разрешить появляющиеся в нем конфликты. Я так подозреваю, гонка на реализацию рефлекшина стартанула, а там уже подтянется первым ) того и тапки
BFE>Далее, template for не нужен.
в gcc часто надо добавлять typename при обращении к вложенному темплиту... using type_ = some_struct::typename calc_some_type<type_arg>::type; а мелкомягких не надо. Вы же говорите об этом, "как вам заблагорассудится", не зная, чем чревато.
BFE>Код относящийся к рефлексии не может выполняться в рантайме, так что template тут лишний, поэтому, кстати, enum_min() должна быть consteval, а не constexpr.
BFE>В целом я бы записал этот пример так: BFE>
BFE>template <typename E>
BFE> requires std::is_enum_v<E>
BFE>consteval E.underlying_type enum_min()
BFE>{
BFE> auto minVal = E.underlying_type.max_value;
BFE> for(auto e : E.entities)
BFE> {
BFE> const auto v = e.value;
BFE> if (v < minVal)
BFE> minVal = v;
BFE> }
BFE> return minVal;
BFE>}
BFE>
BFE>- всё просто и понятно.
мне так не кажется, получается, что мы заморачиваемся еще к куче всевозможных кейсам по модификации типов операторами доступа и прочим, что ломает уже существующие парадигмы.
Впрочем, меня заломало отвечать более развернуто ... кинул к копайлот, и скажем в чем-то я там согласен, и сомнения похожи.
которую вы привели, отражает одну из самых горячих дискуссий в сообществе C++. Это классический конфликт между «прагматичным дизайном» (как это могло бы быть в идеальном новом языке) и «дизайном комитета», скованным обратной совместимостью и необходимостью вписать метапрограммирование в существующую грамматику.
Вот несколько тезисов в ответ на этот разбор:
1. Синтаксис ^E vs E.entities
Автор прав: запись E.entities выглядит естественнее. Однако в C++ точка (.) зарезервирована для доступа к членам объекта. Если разрешить E.entities, где E — тип, возникает неоднозначность с static полями.
Комитет выбрал оператор отражения ^ (reflection operator), чтобы четко разграничить: «сейчас мы работаем не с типом, а с его метаданным описанием». Это позволяет избежать перегрузки парсера, но, безусловно, выглядит «инородно».
2. Сплайсинг [:e:] и метаобъекты
Автор утверждает, что e.value достаточно. Но в текущем черновике рефлексии (P2996) e — это не сам объект, а «дескриптор» (handle) метаобъекта.
Сплайсинг ([:e:]) — это мост из мира метаданных обратно в мир кода.
Без явного сплайсинга компилятору было бы крайне сложно понять, когда вы хотите получить свойство метаобъекта, а когда — превратить метаобъект в реальное выражение (expression), которое можно использовать в коде.
3. template for vs обычный for
Здесь автор затронул фундаментальную проблему. Обычный for в C++ порождает цикл в рантайме. Чтобы превратить итерацию по метаданным в развернутый код (unrolling) или генерацию разных типов на каждой итерации, нужен специальный маркер.
Если оставить обычный for, компилятору придется проводить сложнейший анализ, чтобы понять: «ага, это цикл по константам, я должен его развернуть».
template for явно говорит: «это генерация кода». Это делает поведение предсказуемым.
4. consteval vs constexpr
Автор абсолютно прав в том, что функции, работающие исключительно с метаданными, должны быть consteval. В C++20/23 constexpr функция может быть вызвана в рантайме, а рефлексия в рантайме невозможна. Использование consteval здесь — это не просто хороший тон, а гарантия того, что код не «протечет» в исполняемый файл.
5. Философский вопрос: Революция или Эволюция?
Критика про «монструозную химеру» обоснована. C++ пытается внедрить мощнейшую систему метапрограммирования, не ломая парсеры, написанные 30 лет назад.
Подход автора (в стиле C# или Swift) требует полной переработки модели типов.
Подход комитета — это попытка дать программисту «низкоуровневый ассемблер для типов». Это мощно, но страшно на вид.
Итог
Предложенный автором вариант (E.entities, e.value) — это путь языка с сильной встроенной интроспекцией (как Zig или частично Rust). Путь C++ — это путь библиотечного метапрограммирования, где через страшные символы (^, [: :]) даются фундаментальные возможности, на которых потом напишут красивые обертки.
Согласны ли вы с тем, что C++ стоило бы пожертвовать совместимостью ради чистоты синтаксиса, или гибкость текущего (пусть и сложного) подхода важнее?
Оно там вопрос задает, ..
На счет вашей надежды, что оно завязнет. посмотрим, есть надежда (вполне ощутимые), когда начнут появляться хибернейты, когда реляционные структуры с запросами в SQL с проверкой на этапе компиляции, регекспы с встраеваемыми объектами в запрос ...
Re[6]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, ·, Вы писали:
BFE>>>Эта запись должна выглядеть так: BFE>>>E.entities BFE>·>А что делать, если в E уже есть имя entities? В лучшем случае что-то вроде std::meta<E>::entities.
BFE>Ничего не делать. BFE>E.entities и E::entities — это доступ к разным значениям.
Это ирония ?? Ничего делать, в компайл-коснт классе появится какой-то там "."? еще и разный с class::foo ..
просто переписать компилятор, и всего-то, написать другой фактически. А зачем ? если уже есть ::
Re[7]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, ботаныч, Вы писали:
BFE>>E.entities и E::entities — это доступ к разным значениям. Б> Это ирония ?? Ничего делать, в компайл-коснт классе появится какой-то там "."? еще и разный с class::foo .. Б>просто переписать компилятор, и всего-то, написать другой фактически. А зачем ? если уже есть ::
Никакая это не ирония. Два двоеточия ("::") — это переход по имени, а '.' — это доступ к свойству (к проперти, говоря на сленге). Как их можно перепутать я представляю с трудом. "компайл-коснт" тут вообще ни причём. Нет никакой проблемы в том, чтобы операция доступа к свойствам объекта встречалась в любом контексте. Вас же не смущает, что в коде можно написать sizeof(int) ? Я не вижу причин, почему всякий sizeof(int) нельзя заменить на выражение int.size.
Сейчас, за именем типа не может следовать одна точка (только троеточие), а за именем объекта не может следовать два двоеточия (только одно). Если не согласны — приводите пример.
Поэтому нет никаких проблем с тем, чтобы задействовать точку после имени.
Компилятор переписывать не надо, так как добавление точки — это расширение, а не изменение.
И каждый день — без права на ошибку...
Re[8]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, ботаныч, Вы писали:
BFE>>>E.entities и E::entities — это доступ к разным значениям. Б>> Это ирония ?? Ничего делать, в компайл-коснт классе появится какой-то там "."? еще и разный с class::foo .. Б>>просто переписать компилятор, и всего-то, написать другой фактически. А зачем ? если уже есть ::
AI, предыдущийq промпт сработал лучше, но здесь тоже неплохо
Твое предложение звучит логично и эстетично, но давай называть вещи своими именами: ты предлагаешь не просто «улучшить синтаксис», а фундаментально переписать объектную модель C++.
Вот почему то, что ты описал — это не «эволюция», а создание нового языка:
Смешение сущностей и типов: В твоем примере E.entities или E.underlying_type обращаются к типу как к объекту первого класса через оператор точки. В текущем C++ типы и объекты живут в разных измерениях. Чтобы это заработало, нужно внедрить концепцию, где type — это полноценный объект (как в Python или Zig), что ломает всю классическую парадигму метапрограммирования.
Контекстная неоднозначность: Синтаксис [:e:] (сплайсинг) кажется комитету монструозным, но он решает критическую задачу: четко говорит компилятору, когда мы работаем с метаданными, а когда «впрыскиваем» их обратно в код. Без этого разделителя парсер сойдет с ума, пытаясь понять, является ли e.name строковым литералом или идентификатором новой переменной.
Отказ от шаблонов: Убирая template for, ты предлагаешь компилятору самому догадываться, какой цикл нужно развернуть в compile-time, а какой оставить для рантайма. Это лишает программиста явного контроля, который всегда был «священной коровой» C++.
Комитет идет по пути «химеры» именно потому, что они пытаются приклеить рефлексию к 40-летнему наследию, не ломая старый код. Ты же предлагаешь снести фундамент и построить на нем C++ с человеческим лицом, где типы — это объекты, а метапрограммирование не требует специальных ключевых слов. Это красиво, но это уже не тот C++, к которому привыкли стандартизаторы.
По сути, ты описываешь отказ от шаблонов в пользу чистого метапрограммирования, где всё есть объект. Ты готов к тому, что это фактически убьет обратную совместимость?
На какой компромисс ты бы пошел: оставить монструозный синтаксис, но получить рефлексию завтра, или ждать еще 10 лет идеального дизайна?
BFE>Никакая это не ирония. Два двоеточия ("::") — это переход по имени,
странное определение &classname::field_or_func — синт. выражение времени компиляции, запросто становится параметром шаблона, или складывающего в список типов аля template <typename... Mems> struct Meta; и еще несколько вариаций на эту тему. Впрочем для человека реализовавшего хотя бы один велосипед на эту тему, здесь нет вопросов, уже сейчас до 26-го стандарта. Чего аж вообще не скажешь за оператор точка, который без инстанса (за некоторыми исключениями) рантайма неупотребим.
BFE>а '.' — это доступ к свойству (к проперти, говоря на сленге).
В рантайме, если мы говорим о С++, а не абтрактном языке в вакууме.
BFE>Как их можно перепутать я представляю с трудом. "компайл-коснт" тут вообще ни причём.
Вы почитайте ответ ИИ (мы с ним во много совпадаем). Что там кто путал я не знаю, просто ваше выражение, аж совсем не про С++. BFE>Нет никакой проблемы в том, чтобы операция доступа к свойствам объекта встречалась в любом контексте.
Это как никаких ? Достаточно написать пару грамматик для языка хотя бы имеющего функциональную полноту по Тьюрингу, чтобы иметь представление о разрешении конфликтов, чтобы понимать никакого "Нет никакой проблемы" в этой сфере не существует. А тут разговор про С++, в котором уже предостаточно контекстно зависимых сегментов. А вы именно, что предлагаете — "всего лишь" переписать язык, и менять концепции.
BFE>Вас же не смущает, что в коде можно написать sizeof(int) ? Я не вижу причин, почему всякий sizeof(int) нельзя заменить на выражение int.size.
Да все можно, в пределах разумного, вопрос, кто и сколько времени\денег на это потратит, и когда будет результат. Разговоры про compile time reflection идут давно и велосипедов было написано предостаточно, я сам реализовал парочку, на тех или иных хаках С++ компайлера, есть такая группа в бустовой рассылке — feature SG7. Так вот лучшее, что там получилось так это реализация CTR на базе llvm, с итерабильностью типов по неймспейсам, по мемберам впрочем вы можете зайти да поискать. Этот вариант на гитхабе есть.
BFE>Сейчас, за именем типа не может следовать одна точка (только троеточие), а за именем объекта не может следовать два двоеточия (только одно). Если не согласны — приводите пример. BFE>Поэтому нет никаких проблем с тем, чтобы задействовать точку после имени.
Да не )) конечно никаких проблем, только это не про С++
BFE>Компилятор переписывать не надо, так как добавление точки — это расширение, а не изменение.
жаль я забыл свой промт на который ИИ выдал очень неплохой ответ, но я его почему-то удалил, вместе с промтом. Своими словами что-то вроде за тем, что автор называет "простым и понятным" стоит полное переписывание языка.
Впрочем я вас уверяю попробуйте реализовать хотя бы метаструктуру уже сейчас через макрос с __VA_ARGS__ сложить все мемберы класса в вариэдик, это делается относительно просто. Или грамматику на бизоне с контекстно зависимыми expression, после этой практики ваша уверенность в том, что "все просто" и "ничего менять не надо", станет много меньше.
Хотя можно и без макросов
struct extra
{
void foo0(int, char) { std::cout << "Hello from Robot!" << std::endl; }
std::string foo1() { return"Goodbye!"; }
static void f002() {}
int f0;
std::string f1;
};
template <auto... Mems>
struct Meta
{
};
int main__()
{
using extra_mems = Meta<&extra::foo0
, &extra::foo1, &extra::f0, &extra::f1, &extra::f002>;
return 0;
}
Здравствуйте, B0FEE664, Вы писали:
BFE>Два двоеточия ("::") — это переход по имени, а '.' — это доступ к свойству (к проперти, говоря на сленге).
Ну начинаются удивительные истории. Первый — оператор разрешения видимости (scope resolution operator), второй — оператор доступа к членам (member access operator) — членам-данным, членам-функциям, членам-шаблонам. И тот и другой можно обозначить как "переход по имени". Главное различие в том, что первый применяется к областям видимости (пространствам имен и классам), а второй — к объектам классов.
Причём, через "точку" можно обращаться в т.ч. и к статическим членам классов (главное, чтоб слева от точки было выражение, вычисляющееся в объект). Например: std::true_type{}.value — это обращение к статическому члену std::true_type::value. Или std::numeric_limits<double>{}.epsilon() — то же самое, что std::numeric_limits<double>::epsilon().
--
Справедливость выше закона. А человечность выше справедливости.
привет.
R>Причём, через "точку" можно обращаться в т.ч. и к статическим членам классов (главное, чтоб слева от точки было выражение, вычисляющееся в объект). Например: std::true_type{}.value — это обращение к статическому члену std::true_type::value. Или std::numeric_limits<double>{}.epsilon() — то же самое, что std::numeric_limits<double>::epsilon().
чисто формально std::numeric_limits<double>{}.epsilon() — здесь будет создан инстанс, по моему мнению. в отличии от ::
более близко выглядело бы ((std::numeric_limits<double>*)nullptr)->epsilon(), для статики.
Re[10]: так компайл тайм рефлекшину быть 26-й стандарт ??
Здравствуйте, ботаныч, Вы писали:
Б>Здравствуйте, rg45, Вы писали:
Б>привет.
R>>Причём, через "точку" можно обращаться в т.ч. и к статическим членам классов (главное, чтоб слева от точки было выражение, вычисляющееся в объект). Например: std::true_type{}.value — это обращение к статическому члену std::true_type::value. Или std::numeric_limits<double>{}.epsilon() — то же самое, что std::numeric_limits<double>::epsilon().
Б> чисто формально std::numeric_limits<double>{}.epsilon() — здесь будет создан инстанс, по моему мнению. в отличии от ::
Разумеется, будет создан инстанс, по-моему, я и сам это ясно это обозначил: "главное, чтоб слева от точки было выражение, вычисляющееся в объект".
Хорошо, "то же самое" зачёркриваем. Оставляем только: "через оператор доступа к членам (точку) можно доступаться не только к инстансным, но и к статическим членам". Это было главной мыслью, которую я высказал для полноты картины использования этих двух операторов.
Б>более близко выглядело бы ((std::numeric_limits<double>*)nullptr)->epsilon(), для статики.
Во-первых, это уже другой оператор (->), о котором и речи не шло изначально. Во-вторых, здесь тоже будет создан "инстанс", т.к. указатель — это тоже объект (нулевой указатель в т.ч). Выигрыш по сравнению с созданием объекта пустой структуры сомнителен. В-третьих, я вот думаю, а не будет ли здесь UB (разыменовывание нулевого указателя)? Вот это не очень очевидно для меня — с одной стороны, разыменовывание налицо, с другой — доступа к области памяти, занимаемой объектом нет, this не используется даже формально.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, ботаныч, Вы писали:
Б>>Здравствуйте, rg45, Вы писали:
Б>>привет. R>Хорошо, "то же самое" зачёркриваем. Оставляем только: "через оператор доступа к членам (точку) можно доступаться не только к инстансным, но и к статическим членам". Это было главной мыслью, которую я высказал для полноты картины использования этих двух операторов.
Да я вообще хотел обойти пока стороной вопрос со статикой отмазавшись фразой
Чего аж вообще не скажешь за оператор точка, который без инстанса (за некоторыми исключениями) рантайма неупотребим.
в некоторые исключение как раз входила статика, constexpr, constval выражения в контексте decltype или sizeof(obj.field)
Б>>более близко выглядело бы ((std::numeric_limits<double>*)nullptr)->epsilon(), для статики.
R>Во-первых, это уже другой оператор (->), о котором и речи не шло изначально.
ближе, т.е. без создания инстанса (объекта)
R>Во-вторых, здесь тоже будет создан "инстанс", т.к. указатель — это тоже объект (нулевой указатель в т.ч).
разыменования здесь нет. здесь приведение nullptr к типу, в котором реализован статический метод.
R>Выигрыш по сравнению с созданием объекта пустой структуры сомнителен. В-третьих, я вот думаю, а не будет ли здесь UB (разыменовывание нулевого указателя)? Вот это не очень очевидно для меня — с одной стороны, разыменовывание налицо, с другой — доступа к области памяти, занимаемой объектом нет, this не используется даже формально.
собственно
В выражении ((std::numeric_limits<double>*)nullptr)->epsilon() никакой объект не будет инстанцирован.
Это происходит по следующим причинам:
Статическая природа: Функция epsilon() определена как static constexpr. В языке C++ вызов статического метода через указатель — это лишь синтаксический способ указать компилятору на конкретный тип. Разыменования указателя в реальности не происходит.
Работа компилятора: Для вызова этой функции компилятору достаточно знать тип (std::numeric_limits). Он подставляет значение константы прямо в место вызова еще на этапе компиляции.
Отсутствие UB: Так как фактического обращения к памяти по адресу nullptr не случается, это выражение безопасно и не вызывает неопределенного поведения.
для перехода в точку можно было бы написать (*(std::numeric_limits<double>*)nullptr).epsilon(), но тут уже UB, потому я написал самое близкое и корректное к std::numeric_limits<double>::epsilon().
Но самое забавное, что мы даже не это обсуждаем, мы обсуждаем совсем другую точку, которую предложил коллега B0FEE664.
А именно точка времени компиляции со некими скрытыми итерабильными свойствами времени компиляции. А это немного другой оператор.
Здравствуйте, ботаныч, Вы писали:
R>>Во-вторых, здесь тоже будет создан "инстанс", т.к. указатель — это тоже объект (нулевой указатель в т.ч). Б> разыменования здесь нет.
??? Где ты видишь в ЭТОМ моём высказывании слово "разыменовывание"? Здесь же про другое.
Б>здесь приведение nullptr к типу, в котором реализован статический метод.
Приведение к УКАЗАТЕЛЮ на объекты класса, в котором реализован статический метод, если говорить точнее. Результатом этого приведения является временный объект указателя соответствующего типа. Ещё раз: указатель — это объект, со всеми свойстами, присущими объектам (size, lifetime, storage duration). И размер указателя никак не меньше размера объекта пустой структуры. Скорее всего компилятор соптимизирует создание ненужных временных объектов (как указателя, так и объекта пустого класса), но это уже десятый вопрос.
Б>В выражении ((std::numeric_limits<double>*)nullptr)->epsilon() никакой объект не будет инстанцирован.
Смотри выше. Бутет СОЗДАН объект указателя. И слово "инстанцирование" в С++ обозначает создание воплощений шаблонов, но никак не создание объектов.
Б>более близко выглядело бы ((std::numeric_limits<double>*)nullptr)->epsilon(), для статики. Б>разыменования здесь нет... Б>для перехода в точку можно было бы написать (*(std::numeric_limits<double>*)nullptr).epsilon(), но тут уже UB, потому я написал самое близкое и корректное к std::numeric_limits<double>::epsilon().
На чём основаны эти утверждения? Или ты написал это просто потому, что тебе хочется в это верить? Ну так я тебя огорчу, стандарт C++ утверждает другое:
The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the form using a dot.
Выражение E1->E2 ЭКВИВАЛЕНТНО выражению (*(E1)).E2 (если только операторы '->' и '*' не являются перегруженными функциями). И из этой эквивалентности следует, что разыменовывание указателя имеет место быть в обоих случаях. На счёт UB я по-прежнему не уверен, могу только сказать точно, что оно либо есть в обоих случаях, либо его нет, тоже в обоих случаях.
Б> Но самое забавное, что мы даже не это обсуждаем, мы обсуждаем совсем другую точку, которую предложил коллега B0FEE664. Б>А именно точка времени компиляции со некими скрытыми итерабильными свойствами времени компиляции. А это немного другой оператор.
Здравствуйте, rg45, Вы писали: R>Здравствуйте, ботаныч, Вы писали: R>>>Во-вторых, здесь тоже будет создан "инстанс", т.к. указатель — это тоже объект (нулевой указатель в т.ч). Б>> разыменования здесь нет. R>??? Где ты видишь в ЭТОМ моём высказывании слово "разыменовывание"? Здесь же про другое.
-третьих, я вот думаю, а не будет ли здесь UB (разыменовывание нулевого указателя)?
твоя фраза ?
это 1.
2. ты уводишь тему в разбор, что такое указатель. И ежу понятно, что указатель "имеет" и дестрвуктор, у него есть и прочее соответствующие методы по умолчанию, но память под это все выделяться не будет. т.к. скорее всего будет ссылаться на константную облаcть от типизированных nullptr. Хотя все это чисто для удобства в шаблонировании, и если тебе прилетает в шаблон в качестве template <typename T> void call(T ptr) { ...} using T = ObjectTypePtr*; // то можно вызывать ptr.~T(); //
к чему это обсуждать ? тема несколько вообще про джругое R>Приведение к УКАЗАТЕЛЮ на объекты класса, в котором реализован статический метод, если говорить точнее. Результатом этого приведения является временный объект указателя соответствующего типа. Ещё раз: указатель — это объект, со всеми свойстами, присущими объектам (size, lifetime, storage duration). И размер указателя никак не меньше размера объекта пустой структуры. Скорее всего компилятор соптимизирует создание ненужных временных объектов (как указателя, так и объекта пустого класса), но это уже десятый вопрос. Б>>В выражении ((std::numeric_limits<double>*)nullptr)->epsilon() никакой объект не будет инстанцирован. R>Смотри выше. Бутет СОЗДАН объект указателя. И слово "инстанцирование" в С++ обозначает создание воплощений шаблонов, но никак не создание объектов.
) выше там про reflection по теме, нет у меня времени обсуждать вещи очевидные, инстанцияация шаблонов и инстанса объекта класса, вполне корректные высказывания же) а инстанс, он инстанциируется. Коечно вещи разные с инстанциацией шаблона Б>>более близко выглядело бы ((std::numeric_limits<double>*)nullptr)->epsilon(), для статики. Б>>разыменования здесь нет... Б>>для перехода в точку можно было бы написать (*(std::numeric_limits<double>*)nullptr).epsilon(), но тут уже UB, потому я написал самое близкое и корректное к std::numeric_limits<double>::epsilon(). R>На чём основаны эти утверждения? Или ты написал это просто потому, что тебе хочется в это верить? Ну так я тебя огорчу, стандарт C++ утверждает другое: R>https://timsong-cpp.github.io/cppwp/expr.ref#2 R>
R>The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the form using a dot.
R>Выражение E1->E2 ЭКВИВАЛЕНТНО выражению (*(E1)).E2
Это в теории, а на практике я встречал ситуации падение сразу после разыменования указателя. И в тоже время -> работал без проблем, даже с нестатическими методами, если в методе не было обращений к полям инстанса класса (невалидного). R>(если только операторы '->' и '*' не являются перегруженными функциями). И из этой эквивалентности следует, что разыменовывание указателя имеет место быть в обоих случаях. На счёт UB я по-прежнему не уверен, могу только сказать точно, что оно либо есть в обоих случаях, либо его нет, тоже в обоих случаях.
Ага, особенно если посадят куда-то внутрь клауд системы, и ты свою утилзу будешь запускать на каких-то экзотических стойках с такими-же экзотическими процами. R>Ну так я и писал только о тех двух операторах, о которых шла речь: https://rsdn.org/forum/cpp/9068221.1
R>>>>Во-вторых, здесь тоже будет создан "инстанс", т.к. указатель — это тоже объект (нулевой указатель в т.ч). Б>>> разыменования здесь нет.
R>>??? Где ты видишь в ЭТОМ моём высказывании слово "разыменовывание"? Здесь же про другое. Б>
Б>-третьих, я вот думаю, а не будет ли здесь UB (разыменовывание нулевого указателя)?
Б> твоя фраза ?
Конечно моя, но отвечаешь же ты не на эту, а на другую.
Б>это 1. Б>2. ты уводишь тему в разбор, что такое указатель.
Ничего я никуда не увожу, говорю строго по факту того, что говоришь ты.
Б> И ежу понятно, что указатель "имеет" и дестрвуктор, у него есть и прочее соответствующие методы по умолчанию, но память под это все выделяться не будет.
Под что не будет выделяться память, под указатель??? То есть у указателя есть size и storage duration, но память выделяться не будет?
Б> т.к. скорее всего будет ссылаться на константную облаcть от типизированных nullptr.
А "константная область" — это не память что ли? "Скорее всего" никаких объектов вообще не будет создано, ибо незачем. Только это никак не делает твои высказывания (цитировать не стану) корректными.
Б> Хотя все это чисто для удобства в шаблонировании, и если тебе прилетает в шаблон в качестве template <typename T> void call(T ptr) { ...} using T = ObjectTypePtr*; // то можно вызывать ptr.~T(); //
R>>The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the form using a dot.
Б> Это в теории, а на практике я встречал ситуации падение сразу после разыменования указателя. И в тоже время -> работал без проблем, даже с нестатическими методами, если в методе не было обращений к полям инстанса класса (невалидного).
По сути ты мне сейчас говоришь: "не смотри в документ, слушай, что я тебе говорю". Так? Ну и почему я должен учитывать твой опыт с бОльшим приоритетом, чем стандарт языка?
Б> И в тоже время -> работал без проблем, даже с нестатическими методами, если в методе не было обращений к полям инстанса класса (невалидного).
И кстати, вот это просто хрестоматийный случай UB, который здесь уже жёван-пережёван не один раз на протяжении многих лет. То, что ты используешь подобный говнокод (даже если не используешь, а просто пытаешься строить на этом какие-то рассуждения и делать какие-то выводы) красноречиво говорит о твоей квалификации и о твоей экспертности.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали: R>Здравствуйте, ботаныч, Вы писали:
R>>>>>Во-вторых, здесь тоже будет создан "инстанс", т.к. указатель — это тоже объект (нулевой указатель в т.ч). Б>>>> разыменования здесь нет. R>>>??? Где ты видишь в ЭТОМ моём высказывании слово "разыменовывание"? Здесь же про другое. Б>>
Б>>-третьих, я вот думаю, а не будет ли здесь UB (разыменовывание нулевого указателя)?
Б>> твоя фраза ? R>Конечно моя, но отвечаешь же ты не на эту, а на другую.
ну так она же звучит в контексте. R>Ничего я никуда не увожу, говорю строго по факту того, что говоришь ты.
уводишь уводишь, я говорю компайл тайм рефлекшине, о чем ты? О памяти ? R>Под что не будет выделяться память, под указатель??? То есть у указателя есть size и storage duration, но память выделяться не будет?
под указатель под указатель. Б>> т.к. скорее всего будет ссылаться на константную облаcть от типизированных nullptr. R>А "константная область" — это не память что ли? "Скорее всего" никаких объектов вообще не будет создано, ибо незачем. Только это никак не делает твои высказывания (цитировать не стану) корректными. R>Что за ... ???
call(T ptr) { ptr.~T(); } злой ты .. не буду я с тобой дальше говорить — не о чем. свел беседу о CTR в мурыжыние об указателях. R>>>https://timsong-cpp.github.io/cppwp/expr.ref#2 R>>>
R>>>The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the form using a dot.
R>По сути ты мне сейчас говоришь: "не смотри в документ, слушай, что я тебе говорю". Так? Ну и почему я должен учитывать твой опыт с бОльшим приоритетом, чем стандарт языка?
Нет я говорю, — не морочь мне голову в тех вопросах, в которых я без тебя неплохо разбираюсь и говори по теме. И намекнул, что стандарт стандартом, а реальность реальностью. Больше ничего. ратовать за правду и стандарт, это правильно, желаю удачи в описанных мною кейсах. Сядешь и будешь махать бумажкой стандарта, когда у тебя будет валиться стойка. С описанными багами. R>И кстати, вот это просто хрестоматийный случай UB,
Перечитай выше, а лучше сходи еще посмотри на деревья с пулевыми отверстиями которых ты не нашел ... R>который здесь уже жёван-пережёван не один раз на протяжении многих лет. То, что ты используешь подобный говнокод (даже если не используешь, а просто пытаешься строить на этом какие-то рассуждения и делать какие-то выводы) красноречиво говорит о твоей квалификации и о твоей экспертности.
кто сказал, что я не понимаю, что это UB? равно как и (*E).foo();
давай так, эксперт ? покажи свой велосипед по CTR. Много где использовал? Сколько вариантов
П.С. я себя вообще себя экспертом не считаю, мне ставят задачу, и я ее решаю. У меня инфраструктурные построения в архитектуре С++, вообще почти всегда в компайл тайме. Где такие баги как ты описываешь в принципе не появляются.
Если тебе пофигу на CTR, тол не мешай пообщать с теми кому нет.
Хотя CTR высоко-концептуальная фича, не обсуждать это а лезть в рантайм)), это ты же первый начал тут за рантайм в этом контексте?? Эксперт ..
собраюсь вот сделать на основе этой CTR. Позарегаю типы, на основе механизма, чем-то напоминает, тот вариант что предлагал ремарк, только проще чтобы в тайплисты пособирать всю мета, и там будет дальше с компайл тайм строками. Буду пытаться запустить велосипед в космос.
помнится по этому поводжу с тобой тоже какой то срач вышел.
Вместо конструктивной беседы, я грю __PRETY_FUNCTION__ и __FUNCSIG__ вещи разные принципиально тем, что pragma message одну берет, а другую нет, и на основе __FUNCSIG__ можно дебажить инстанциацию шаблонов, а на основе __PRETY_FUNCTION__ нгет. а ты как вцепился в какую то чушь.