LINUX.ORG.RU

ANSI C++: вычисление дробной степени (SFINAE)

 , , , ,


0

2

Всем привет!

Подскажите пожалуйста, как в классическом C++ можно с помощью шаблонов, принципа SFINAE посчитать результат возведения положительного дробного числа в положительную дробную степень во время компиляции.

Общая идея:

a^x = exp(x * ln(a))

В свою очередь ln(a) можно разложить в ряд Тейлора:

ln(a + 1) = [ a / (1!) ] - [ a^2 / (2!) ] + [ a^3 / (3!) ] - ...

Экспонента тоже раскладывается в ряд Тейлора:

exp(p) = 1 + [ p / (1!) ] + [ p^2 / (2!) ] + [ p^3 / (3!) ] + ...

Вроде бы дело не хитрое, надо рекурсивно вызывать шаблоны и все получится. Но в C++ нельзя получить дробные аргументы шаблона.

Собственно вопрос: подскажите как можно обойти это ограничение и таки посчитать a^x в compiletime.

★★★

Последнее исправление: zx_gamer (всего исправлений: 1)

Ответ на: комментарий от zx_gamer

Есть констекспр. Твоя бездарность никого не волнует, твоя шиза никому не нужна. Еще один бегун с кочергой в жопе.

P.S. мало тебя в pro.cxx «раскритиковали».

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от zx_gamer

Хочется выжать из компилятора «невозможное» — сделать то, что авторы языка и не предполагали возможным

Сделай свой ЯП для этого, а не насилуй пользователей чужого. Тебе boost мало, еще хочешь шаблонную магию?

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от Siborgium

Вы очень правильно поставили слово «раскритиковали» в кавычки. Потому что «критики» никакой и не было. Содержимое этой т.н. «критики» было примерно как у вас сейчас, а именно обвинение меня в некомпетентности без какого-либо объяснения того, почему я не прав.

zx_gamer ★★★
() автор топика
Ответ на: комментарий от zx_gamer

без какого-либо объяснения того, почему я не прав

Потому что игнорируешь факторы, из-за которых STL сделан так, а не иначе.

Впрочем, если ты считаешь, что так будет лучше для многих - сделай свой вариант С++. Может, на него действительно плюсовики побегут толпами.

anonymous
()

И вот эти люди потом лисперам в носу ковыряться запрещают!

P.S. Любое рациональное число представимо в виде пары целых чисел — числителя и знаменателя. Значит нужно написать свои шаблонные функции для сложения m1/n1 + m2/n2 = (m1×n2 + m2×n1)/(n1×n2) и остальных арифметических действий.

ugoday ★★★★★
()
Ответ на: комментарий от AntonI

Ну обычно подобное метапрограммирование в спортивных целях и практикуется. А раз так - то почему нет. Главное чтоюы эти всякие спортивные цели потом в STL не попадали как куча сомнительных решений из boost

mittorn ★★★★★
()
Ответ на: комментарий от AntonI

А вот доля полезных фич от общего количества в STL только падает.
мало того, если раньше те или иные фичи можно было использовать практически невозбранно, сейчас std::string где-нибудь в аргументах метода приведёт к тому, что его abi будет зависеть от указанного -std компилятора и его версии даже в пределах одного компилятора. Использование std::чегоугодно приведёт к появлению символов с десятком шаблонных аргументов, котррых ранее не было.
В общем, теперь использовав STL чтобы чуть упростить себе жизнь ещё 10 раз пожалеешь, что не написал вместо этого минимальную реализацию.

mittorn ★★★★★
()
Ответ на: комментарий от zx_gamer

Ну кстати одну (ОДНУ, КАРЛ) полезную вещь в новых стандартах завезли. Это std::string_view. Референс на подстроку без необходимости копирования строки и расчёта размера. Только 2017 год - слишком поздно для такого. Ну и if constexpr тоже в c++17 появился и позволяет избежать раздувания шаблонов через SFINAE

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

Одну? Оглянись вокруг, концерты, deduction guide, filesystem, stacktrace, многопотчные штучки (shared mtx хотя бы) , optional, consrexpr vector/string, модули (один лишь перевод std на модули лишает головной боли с массой include <something_std>),…

Ну да, если та разработчик «высоконагруженных циклов» для обхода строк, то мог и не заметить ничего кроме string_view. Вообще хз как можно сидеть на анси с++ и чего -то писать, даже без smart_ptr’ов.

kvpfs_2
()
Последнее исправление: kvpfs_2 (всего исправлений: 2)
Ответ на: комментарий от kvpfs_2

Вообще хз как можно сидеть на анси с++ и чего -то писать, даже без smart_ptr’ов.

Если кодовая база старая, то в ней может быть куча собственных велосипедов, которые повторяют функциональность STL.

Те же самые smart_ptr народ начал применять еще в середине 1990-х.

Не говоря уже про то, что к части классов из C++ной stdlib есть претензии по части производительности (навскидку вспоминаются std::regex и std::unordered_map/set).

eao197 ★★★★★
()
Ответ на: комментарий от zx_gamer

А что плохого в наследовании? Когда все в хедерах (а шаблоны все равно все в хедерах) компилятор сделает наследование бесплатным. Даже виртуальные функции он может развернуть.

Можно будет писать функции которые получают любой контейнер и что-то с ним делают (получают const IContainer&).

Java головного мозга! STL я могу использовать и для простых raw pointers пришедших из кода на C! Назачем мне этот объект контейнер ?!

necromant ★★
()
Ответ на: комментарий от kvpfs_2

Ок, концепты полезны, я просто обычно не рассматриваю то, что меньше 7 лет назад в стандарт попало
filesystem, stacktrace - этому всему не место в стдлибе языка т. К доверие имплементации тут сомнительное. Это всё должно быть в некотором system api, но никак не в stl. Тотже касается и libc: из-за него приходится костыли вроде флетпаков делать. От многопоточных штук тошнит уже. Опять вместо языковой конструкции для атомиков добавили какой-то шаблонный буллшит.
Модули никому нафиг не сдались в таком виде как сейчас.

smart_ptr

Да в гробу я видел эти smart_ptr. Концепция может и хорошая, но когда деструкторы большого однопоточного приложения подвисают на несколько секунд пытаясь синхронизировать удаление этих smart_ptr- понимаешь что в тауом виде он не нужен.Почти все. Лишняя синхронизация в контейнере не сделает однопоточный код многопоточным. Зато иллюзия потокобезопасности откроет тысячи способов отстрелить себе всё тело вместо пальца.
штуки, которые добавили в STL можно сделать самому и будет лучше.
Да, если попопаться в c++20-c++23 - можно много чего найти. Только вот не полезного, а скорее необходимого, без которого фичи из c++17 просто нормально не работают.
например if consteval, без которого constexpr из-за его ограничений практически непригоден. Тот же fmt (который за каким-то фигом в стандарт пизнули) под c++17 рпзваливается на форматировании некоторых double
bit_cast опять же без которого распарсить double по битам в constexpr нельзя.
Да и в stl интересных фич подвезли вроде полиморфных ресурсов. Опять же реализовав самостоятельно получишь нечто более эффективное для своих задач, хоть и с pmr хотя бы многие инструменты STL обретают смысл.

mittorn ★★★★★
()
Ответ на: комментарий от eao197

Если кодовая база старая, то в ней может быть куча собственных велосипедов, которые повторяют функциональность STL

Так людям не нужно, об этом говорят, зачем же её повторять. Мол вот один лишь string_view полезный завезли и всё, остальное шлак

Те же самые smart_ptr народ начал применять еще в середине 1990-х.

И родил говно под названием auto_ptr, которое без move нормально не запилить

Не говоря уже про то, что к части классов из C++ной stdlib есть претензии по части производительности (навскидку вспоминаются std::regex и std::unordered_map/set).

Ох уже эти тесты с голым for и 100500 операций над map’ом, unordered_map от Васяна быстрее на наносекунду (на одну операцию)! В реальности, где есть какая-то полезная нагрузка, всего этого видно не будет. И вопрос под оптимизацию под конкретные условия открытый, где гарантия, что в других условиях хеш функция васянского мэпа не будет давать кучу коллизий? Я даже не хочу себе голову парить этим, просто юзаю, написать достаточно годную и универсальную реализацию - проблемы не мои. Если вдруг это когда-нибудь станет узким местом, то заюзаю что-нибудь другое

kvpfs_2
()
Последнее исправление: kvpfs_2 (всего исправлений: 1)
Ответ на: комментарий от kvpfs_2

И родил говно под названием auto_ptr, которое без move нормально не запилить

Что было возможно в рамках тогдашнего C++, то и запилили.

Позволю себе напомнить, что shared_ptr и weak_ptr пришли в C++ из Boost-а, а бустовские версии были еще для C++98 сделаны.

Ох уже эти тесты с голым for и 100500 операций над map’ом, unordered_map от Васяна быстрее на наносекунду (на одну операцию)!

И тут такой эспертный эсперт заявляет: фигня это все, я не парюсь и другим советую.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Позволю себе напомнить, что shared_ptr и weak_ptr пришли в C++ из Boost-а, а бустовские версии были еще для C++98 сделаны.

Ну правильно, а вот нормальный unique_ptr - проблема, а shared_ptr может быть излишен

И тут такой эспертный эсперт заявляет: фигня это все, я не парюсь и другим советую.

Как и тесты в вакууме. Надо профилировать конкретный полезный код и смотреть - является ли контейнер узким местом, только тогда делать выводы

kvpfs_2
()
Ответ на: комментарий от mittorn

Ок, я переубеждать не собираюсь. Лично в своих целях активно юзаю и смарт_птр и bind и function, многопоточные штуки, всё норм. Без новых стандартов было бы реально тяжко (ну пришлось бы что-то тянуть со стороны, boost там и прочее). И в страшном сне я видел - переизобретать собственную std самостоятельно

kvpfs_2
()
Ответ на: комментарий от kvpfs_2

Ох уже эти тесты с голым for и 100500 операций над map’ом, unordered_map от Васяна быстрее на наносекунду (на одну операцию)!

Старый хэшмап ускоряет боевой код в полтора раза.

AntonI ★★★★★
()
Ответ на: комментарий от mittorn

Птр напиши, функшен напиши, мэп,… . И будешь в итоге сидеть у горы разбитой васянки, которую пилил вместо решения своей задачи. Я однажды так пол года в унитаз спустил, вроде даже получилось что-то, но так и не заюзал велосипед.

kvpfs_2
()
Ответ на: комментарий от mittorn

std::string где-нибудь в аргументах метода приведёт к тому, что его abi будет зависеть от указанного -std компилятора и его версии даже в пределах одного компилятора

Так правильно, комитет никогда не заботили вопросы ABI

static_lab ★★★★★
()
Ответ на: комментарий от mittorn

А что здесь правильного то, если результат их работы годится только на поиграться?

Буквально «только на поиграться»?

Вы хотите сказать, что работаете над проектами, где нет ни std::string, ни std::vector, ни std::set, ни std::function, ни одного вызова функции из <algorithm>, никаких std::back_inserter и пр.?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

В safety-critical проектах действительно не бывает ничего из выше перечисленного.
В менее критичных проектах по работе же использую std::string и std::vector, причём первый периодически заставляет ругаться в отладчике, т.к отладчик цепляет контекст от заинлайненных методов std::string если конструктор вызывается при передаче в функцию или возврате. Ну, unordered map ещё может пригодиться. При этом STLовые классы обёрнуты в using с другим именем, чтобы можно было прозрачно заменить реализацию.
В домашнем проекте STL нет и не будет, хотя активно задействованы возможности c++17:
https://gitlab.com/mittorn/xrBinder
Там нет аналога std::string потому что аналог string_view - куда проще и эффективнее. Контейнеры сами выделяют память под него.

Замечу так же что imgui - весьма немаленький проект, который наотрез отказывается использовать STL и от этого нисколько не теряет. Да, у него есть своя маленькая реализация vector, так же автор предлагает реализацию string (которая тем не менее в imgui не используется)
Всё жду, когда ветку с поддержкой string_view-like строк вмержут.

Да вообще, свои утилиты повсеместно. Qt, llvm, игровые движки.
Даже если в коде используется STL, всё равно для эффективности приходится держать свои реализации.
в Source всю жизнь был свой набор утилит, который только недавно стал использовать куски STL, и то лишь потому что движок стал превращаться в помойку:
https://github.com/ValveSoftware/GameNetworkingSockets/blob/master/src/public...

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

В safety-critical проектах действительно не бывает ничего из выше перечисленного.

Вы про свои safety-critial проекты говорите? Или где-то в MISRA зафиксировано, что std::find_if под тотальным запретом?

В домашнем проекте STL нет и не будет, хотя активно задействованы возможности c++17: https://gitlab.com/mittorn/xrBinder

Так домашние проекты на то и домашние, чтобы автор мог извращаться как хочет.

Кстати, и давно у вас обычный new может nullptr возвращать?

		mpszData = new char[muiLength + 1];
		if(mpszData)

Заодно интересно, а что будет если он таки nullptr возвратит? Неужели _LoadFile оставит IniParser в корректном состоянии?

Замечу так же что imgui - весьма немаленький проект, который наотрез отказывается использовать STL и от этого нисколько не теряет.

Только вот заглядывать в кишки Dear ImGUI то еще удовольствие. Как и разбираться с документацией к оному.

Да вообще, свои утилиты повсеместно. Qt, llvm, игровые движки.

На счет LLVM вы точно уверены?

https://github.com/llvm/llvm-project/blob/400d4fd7b6dea9c7cdd255bb804fcd0ee77f6d42/llvm/lib/IR/AttributeImpl.h#L288-L296

eao197 ★★★★★
()
Ответ на: комментарий от eao197
  1. в HPC (числодробилках). Тому есть много причин, на самом деле вся мощща STL в числодробилках обычно ненужна, там проблемы совсем в другой плоскости лежат. Ну и тот же std::vector слишком непонятная местами вещь, кое кто из коллег ЕМНИП так и не смог добиться от него нужного выравнивания хотя они C++ знают значительно лучше меня.

  2. Если только на гитхабе чей то чужой. Но с т.з «обычного» программиста этот код как правило ужасен;-)

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от AntonI

А вот в HPX, например, и std::vector, и std::string используются. Полагаю для вспомогательных вещей, но тем не менее.

В разговоре о числодробилках, имхо, вероятнее было бы услышать про проблемы с std::valarray, а не std::vector.

Но с т.з «обычного» программиста этот код как правило ужасен;-)

Насколько я помню, код от вычислительных математиков (да и физиков тоже) был ужасен просто потому, что из этих самых вычислительных математиков хоть как-то программировать умели хорошо если каждый пятый.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

проблемы с std::valarray

Это тупиковая ветвь эволюции, используется крайне редко. Ну и такие велосипеды мы и сами прекрасно писать умеем.

из этих самых вычислительных математиков хоть как-то программировать умели хорошо если каждый пятый.

Это одна из причин, и она не главная. Условия и специфика разработки числодробилок и какого нить веб-браузера (я ХЗ че там настоящие программисты обычно разрабатывают) кардинально отличаются. Скажем за геттеры/сеттеры без веского обоснования у нас бьют по пальцам клавой, в имени переменной главное требование - совпадение с записью численной схемы (т.е. имя из одной буквы это норма) и т.д.

AntonI ★★★★★
()
Ответ на: комментарий от eao197

Заодно интересно, а что будет если он таки nullptr возвратит? Неужели _LoadFile оставит IniParser в корректном состоянии?

Верно подмечено, muiLength там не сброшен, хотя пригодность класса к использованию у меня определяется именно mpszData (см. operator bool), так что не должно быть критичным

Только вот заглядывать в кишки Dear ImGUI то еще удовольствие. Как и разбираться с документацией к оному.

Куда лучше чем fmt, код которого проще читать в декомпиле и здесь я даже не приувеличиваю - реально так делал чтобы понять, почему он был быстрее моей реализации printf. В сорцах понять там что-либо очень сложно

На счет LLVM вы точно уверены?

Я не говорю о том, что STL в этих проектах не используется. Я лишь говорю, что вместо многих контейнеров, присутствующих в STL там свои собственные реализации и на это есть причины. Даже приведённый мной в соседнем посте пример сурсовских утилит использует type_traits, только вот долгое время он был без него и большая часть это всё не использует.

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

Не знаю правда, реализация может и cxa_terminate вызвать, не проверял

И, скорее всего, вызовет. Проверил только что на wandbox-е, именно так и работает.

Вам бы в сторону nothrow посмотреть (цынк).

eao197 ★★★★★
()
Ответ на: комментарий от AntonI

Это одна из причин, и она не главная.

Ну да, ну да.

Скажем за геттеры/сеттеры без веского обоснования у нас бьют по пальцам клавой

Геттеры-сеттеры – это вообще какой-то карго-культ. Их в последние 15-20 лет стало принято лепить по умолчанию не приходя в сознание.

Кстати говоря, вы замеряли, есть ли какие-то накладные расходы для геттеров вида:

class Values {
  int m_x;
  ...
public:
  [[nodiscard]] int x() const noexcept { return m_x; }
  ...
};

?

eao197 ★★★★★
()
Ответ на: комментарий от mittorn

Я лишь говорю, что вместо многих контейнеров, присутствующих в STL там свои собственные реализации и на это есть причины.

Нормальное явление когда начинают разработку с использованием контейнеров из STL, а когда получается первая рабочая версия и проводят профилирование, то узкие места расшивают посредством других типов контейнеров.

Хотя бывают и случаи, когда заранее известны и условия, и требования. Тогда сразу можно взять условный boost::flat_set или absl::flat_hash_map.

При этом, если сторонние контейнеры мимикрируют под STL-ные контейнеры, то менять STL-ный на не-STL-ный и наоборот, оказывается не просто, а очень просто.

И такая практика выглядит гораздо более здравой, чем желание написать свой HashMap просто потом, что STL-ный тормознут или потому, что вы чего-то не видите под отладчиком.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

есть ли какие-то накладные расходы для геттеров вида

Не замерял. Основная претензия к геттерам/сеттерам (у нас) ухудшение читемости кода. Я понимаю зачем они нужны в проекте на млн строк кода который пишут и пепеписывают дцать человек. У нас проекты по 10к строк над которыми работает макс трое.

Численная схема занимающая несколько страниц А4 арабской вязи с геттерами и сеттерами становится вообще нечитаемой. Отсюда же толстые функции на несколько экранов растут…

Я сам уже давно не считаю себя программистом:-)

AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)