Предпочтительный способ вычислений во времени компиляции
От: sergii.p  
Дата: 29.08.19 15:09
Оценка: :)
собственно в C++, есть два способа делать одно и то же.
Например посчитать факториал можно с помощью инстанциирования шаблонов:

template<int Val>
struct factorial: std::integral_constant<int, Val * factorial<Val - 1>>{};

template<>
struct factorial<0>: std::integral_constant<int, 1>{};


Здесь при расчёте factorial<5> последовательно инстанциируются шаблоны factorial<5>, factorial<4>, factorial<3>, factorial<2>, factorial<1> и factorial<0>. Некоторые умные люди говорят, что это бьёт по времени компиляции (точнее по памяти компилятора). На каждый инстанс надо завести память и эту память компилятор освободить никак не сможет до окончания компиляции. С другой стороны, скорость вычислений потенциально может вырасти за счёт кэширования. Хотя, насколько я знаю, большинство компиляторов действуют по другому алгоритму и инстанциируют по-жадному всё что видят. То есть вроде как плюсов получается совсем нет, одни накладные расходы.

Другой способ в constexpr функциях

constexpr int factorial(int val)
{
    if(val == 0) {
        return 1;
    }
    else {
        return val * factorial(val - 1);
    }
}


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

Вроде выбор напрашивается. Надо предпочитать constexpr функции. Но если смотреть реализации stl, то получается многие идут по первому пути (н-р реализация наибольшего общего делителя _gcd из std::ratio для gcc и msvc). Значит есть какие-то проблемы с constexpr подходом. Так вот какие?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.