Заметил, что значительная часть нескольких последних стандартов иделяется этой части языка. Даже вот consteval появился. А насколько это реально нужно на практике? Точнее, у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает? Вообще существуют ещё языки, где есть что-то подобное?
Здравствуйте, cppguard, Вы писали:
C>Заметил, что значительная часть нескольких последних стандартов иделяется этой части языка. Даже вот consteval появился. А насколько это реально нужно на практике? Точнее, у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает? Вообще существуют ещё языки, где есть что-то подобное?
Хотя rg45 и критиковал мою концепцию, однако все-же C++ разделятся на два разных подъязыка:
1. С++ времени компиляции.
2. C++ времени исполнения.
Это два разных языка, первый можно даже не использовать, при этом можно будет написать любую программу.
Первый ограничен — там нет возможности взаимодействия с системой, динамической памяти и пр. Но он довольно сложен, в чем-то даже более мозгодробилен, чем классический C++ времени исполнения.
Время компиляции допускает не так уж много конструкций. Интересные примеры:
Цикл, казалось бы:
constexpr int sumUpTo(int n)
{
int sum = 0;
for (int i = 1; i <= n; ++i)
sum += i;
return sum;
}
constexpr int sum = sumUpTo(10);
А вот if — не умеет, нужно только if constexpr:
template <typename T>
constexpr auto process(T value)
{
if constexpr (std::is_integral_v<T>)
return value * 2; // Вычисляется, если T — целое числоelse
return value / 2;
}
constexpr int result = process(5); // Результат 10
И даже
struct Point
{
int x, y;
constexpr Point(int x, int y) : x(x), y(y) {}
constexpr int distance() const { return x * x + y * y; }
};
constexpr Point p(3, 4);
constexpr int dist = p.distance();
Ваш вопрос мне так же интересен, но пока он для меня открыт. Имхо, какая-то ошибка концептуальная возникла, из-за чего пришлось добавлять подъязык в языке.
Самое парадоксальное, что при всей сложности этого подъязыка — он не позволяет полноценно сделать ORM, чтобы сделать что-то типа LINQ и оно само транслировалось в полноценные SQL-запросы. Только простые какие-то вещи можно сделать типа счетчика (и то будет тонна запутанного кода), но не реально полезные.
Здравствуйте, cppguard, Вы писали:
C>Заметил, что значительная часть нескольких последних стандартов иделяется этой части языка. Даже вот consteval появился. А насколько это реально нужно на практике? Точнее, у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает? Вообще существуют ещё языки, где есть что-то подобное?
Баловство всё. Вычисления можно делать еще до компиляции и генерировать код уже с правильными константами.
Здравствуйте, kov_serg, Вы писали:
_>Баловство всё. Вычисления можно делать еще до компиляции и генерировать код уже с правильными константами.
Дык вручную может быть не удобно, притом что результат может зависеть от платформы. Вот чел. сделал счетчик времени компиляции — http://rsdn.org/forum/cpp/8858730.flat
Здравствуйте, cppguard, Вы писали:
C>А насколько это реально нужно на практике?
Изредка. Но когда нужно, тогда хз чем надежно заменить, особенно если итоговая система сборки тебе не подконтрольна и применимость внешней кодогенерации под вопросом (например, когда ты делаешь и распространяешь header-only библиотеку).
C>Точнее, у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает?
Маленький пример. Здесь constexpr нужен чтобы определить тип, который затем будет возвращаться методом make_c_string. Если у вас получится определить тип во время компиляции каким-то "единовременным вычислением на стадии инициализации", то constexpr вам вряд ли нужен.
ЗЫ. Любители чистого Си и старого-доброго Си-с-классами могут сказать, что это все баловство, и можно написать как диды писали:
Здравствуйте, Shmj, Вы писали:
S>А вот if — не умеет, нужно только if constexpr:
S>
S>template <typename T>
S>constexpr auto process(T value)
S>{
S> if constexpr (std::is_integral_v<T>)
S> return value * 2; // Вычисляется, если T — целое число
S> else
S> return value / 2;
S>}
S>constexpr int result = process(5); // Результат 10
S>
Здравствуйте, so5team, Вы писали:
S>Иногда лучше жевать, чем говорить (c)
Да, извиняюсь, работает и без constexpr if. В свое оправдание могу сказать что не приходилось вообще использовать сложные конструкции во время компиляции и пока не особо вижу в них смысл.
Здравствуйте, Shmj, Вы писали:
S>Да, извиняюсь, работает и без constexpr if. В свое оправдание могу сказать что не приходилось вообще использовать сложные конструкции во время компиляции и пока не особо вижу в них смысл.
Ну вот и выходит, что все твои "концепции" находятся в области интерпретаций и субъективного восприятия. Которые к тому же часто заставляют путать тебя тёплое с мягким. Нет, конечно, ты можешь искать для себя лично какие-то собственные взгляды на предмет, если тебе так проще. Но навязывать свои "концепции" широкому кругу своего общения, наверное, не стоит. Если не хочешь сталкиваться с негативом на каждом шагу.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>Ну вот и выходит, что все твои "концепции" находятся в области интерпретаций и субъективного восприятия. Которые к тому же часто заставляют путать тебя тёплое с мягким. Нет, конечно, ты можешь искать для себя лично какие-то собственные взгляды на предмет, если тебе так проще. Но навязывать свои "концепции" широкому кругу своего общения, наверное, не стоит. Если не хочешь сталкиваться с негативом на каждом шагу.
Да этот if constexpr ничего не меняет.
Вот взять код:
#include <iostream>
constexpr int multiply(int a, int b)
{
return a * b;
}
constexpr int square(int x)
{
return multiply(x, x);
}
int main()
{
constexpr int result = square(5);
std::cout << "Result: " << result << std::endl;
return 0;
}
Здесь square — функция времени компиляции. И она имеет право вызывать только функции времени компиляции. Как бы уже разделение, не совместимые вещи.
Шаблоны, концепты и пр. лабуда — это только и исключительно только времени компиляции.
Здравствуйте, Shmj, Вы писали:
S>Здесь square — функция времени компиляции. И она имеет право вызывать только функции времени компиляции. Как бы уже разделение, не совместимые вещи.
Здравствуйте, Shmj, Вы писали:
S>Здесь square — функция времени компиляции. И она имеет право вызывать только функции времени компиляции. Как бы уже разделение, не совместимые вещи.
Примеров по схеме "вот так можно, а вот так нельзя" можно придумать громадное количество. Но это ж всё не поводы для разбиения на "подъязыки".
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Shmj, Вы писали:
S>Шаблоны, концепты и пр. лабуда — это только и исключительно только времени компиляции.
Да я вам даже больше скажу: class и struct, да что там, даже int или float -- это только и исключительно времени компиляции. Потом никаких классов и структур как run-time сущностей нет.
Здравствуйте, cppguard, Вы писали:
C>насколько это реально нужно на практике?
В общем случае constexpr/consteval полезны хотя бы для того, чтобы явно указать "всё необходимое для вычисления должно быть известно на этапе компиляции, иначе у нас что-то не так с концепцией". Просто как одна из форм static assert.
C>у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает?
Чтоб прям проигрывало, нужны очень жесткие требования по ресурсам. В каком-нибудь мелком МК перенос вычисления в рантайм запросто может привести к невлезанию прошивки в память, а на сколько-нибудь серьезных платформах это чаще всего незаметно.
Здравствуйте, cppguard, Вы писали:
C>Заметил, что значительная часть нескольких последних стандартов иделяется этой части языка. Даже вот consteval появился. А насколько это реально нужно на практике? Точнее, у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает? Вообще существуют ещё языки, где есть что-то подобное?
Не стоит смотреть на вычисления времени компиляция только лишь как на средство оптимизации быстродействия. Константы времени компиляции могут участвовать в образовании типов и определении концептов, участвовать в overload resolution и пр. Да и сами константы сейчас это уже не только числа, но и объекты классов, позволяющие эффективно выстраивать системы типов со статическим полиморфизмом, расскладывать сложные задачи на подзадачи и стратегии, обеспечивать возможность определять моки для юнит-тестов и много чего еще.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, cppguard, Вы писали:
C>Заметил, что значительная часть нескольких последних стандартов иделяется этой части языка. Даже вот consteval появился. А насколько это реально нужно на практике? Точнее, у вас есть реальный пример, когда это было настолько нужно, что эквивалентоное единовременное вычисление на стадиции инициализации программы сильно проигрывает? Вообще существуют ещё языки, где есть что-то подобное?
В метапрограммировании — пользуемся почём зря.
Там не прямо вычисления-вычисления, но элементарно, параметризовать что-то в зависимости от размера данных или от булевых флажков со свойствами — помогает.
Доля таких constexpr в общей массе кода маленькая, но ненулевая.
Ещё одна вещь, где constexpr прямо очень нужен — статические константы.
struct foo {
foo(.....) {.....}
.....
};
struct bar {
constexpr bar(.....) {.....}
.....
};
/* static */const foo g_f; // ложится в секцию данных, выполняет конструктор перед main
/* static */const bar g_b; // ложится в секцию констант
Если ты не сталкивался с гонкой статических конструкторов, — ты счастливый человек, и у тебя все грабли впереди.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, kov_serg, Вы писали:
_>>Баловство всё. Вычисления можно делать еще до компиляции и генерировать код уже с правильными константами.
S>Дык вручную может быть не удобно, притом что результат может зависеть от платформы. Вот чел. сделал счетчик времени компиляции — http://rsdn.org/forum/cpp/8858730.flat
Здравствуйте, cppguard, Вы писали:
C>Здравствуйте, kov_serg, Вы писали:
_>>Баловство всё. Вычисления можно делать еще до компиляции и генерировать код уже с правильными константами.
C>Так вот и я клоню в эту сторону. Кодогенерация была задолго до constexpr и хорошо работала.
Именно. Вот следовало бы добавить препроцессор типа lua до этапа компиляции в стандарт и не канифолить мозг.
Скрипты могут сделать на порядок больше и удобнее чем извращаться с метапрограммирование на недо-шаблонах.
Здравствуйте, so5team, Вы писали:
S>Да я вам даже больше скажу: class и struct, да что там, даже int или float -- это только и исключительно времени компиляции. Потом никаких классов и структур как run-time сущностей нет.
Есть разница где и когда происходит калькуляция, т.е. компьютинг — в момент компиляции на машине разработчика или в момент запуска на машине пользователя. Пример:
#include <iostream>
constexpr int fun1(int x)
{
return 100 / x;
}
int main()
{
constexpr int result = fun1(0);
std::cout << "Result: " << result << std::endl;
return 0;
}
— такой код даже не скомпилируется, вы не сможете сделать исполняемый файл.
А вот так:
#include <iostream>
int fun1(int x)
{
return 100 / x;
}
int main()
{
int result = fun1(0);
std::cout << "Result: " << result << std::endl;
return 0;
}
— вы уже сможете собрать исполняемый файл, дать его пользователю чтобы баг произошел на его стороне.
Разница есть?
Притом, когда попытаетесь собрать все конструкции, которые можно использовать в момент компиляции — окажется что их не так уж много. Но они самые мозгодробильные.