C++, Сложные вычисления на этапе компиляции
На Лиспе можно.
Однажды я написал пачку макросов которые компилируются пару минут и требуют десять гигабайт памяти при этом. Этот кода кусок до сих пор там торчит и радует при каждой сборке. Оно тебе надо? Лучше написать отдельный кусок кода который будет исполняться на компиляции и генерировать то что нужно.
#include <iostream>
#include <array>
constexpr size_t ndc_helper(const char* str, const size_t length, size_t pos,
std::array<bool, 256> seen_chars) {
return pos != 0) ? (seen_chars[(unsigned char)str[pos - 1]] = true) : true
(pos < length
? (!seen_chars[(unsigned char)str[pos]] +
ndc_helper(str, length, pos + 1, seen_chars
: 0;
}
template <size_t L>
constexpr size_t ndc(char (&str)[L]) {
return (L == 1) ? 0 : ndc_helper(str, L - 1, 0, std::array<bool, 256>
}
int main {
char str[] = "abcdefgabcdefggfedcba";
std::cout << ndc(str) << std::endl;
}
Но можно сделать то же самое и в C++98, используя рекурсивное инстанцирование шаблонов.
Если мне изменяет память, Александреску помимо списков типов, делал еще и множества.
UPD: переписал код немного. В первой версии было UB.
http://gergo.erdi.hu/projects/metafun/
А можно взять D:
int uniqueChars(string s)
{
bool[char] chars;
foreach(c; s) chars[c] = true;
return chars.values.length;
}
void main(string[] argv)
{
static int n = uniqueChars("mamamylaramy");
writeln(n);
}
Тут static заставляет вычислить функцию при компиляции.
Я бы с удовольствием взглянул на то, как это можно сделать в C++98, ибо, насколько я помню, в C++98 со строками на этапе компиляции могут работать только препроцессорные операторы # и ##, чего для данной задачи совершенно недостаточно.
Удивительно, но это может быть полезно. Я так считал compile-time hash от имён исходных файлов, чтобы они не попали в релизный скомпилированный код (типа obscurity).
В boost-е, например, практикуют всякие извращения:
typedef mpl::string<'hell','o wo','rld'> hello;
typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2;
BOOST_ASSERT(0 == std::strcmp(mpl::c_str<hello2>::value, "hello world!";
http://www.boost.org/doc/libs/1_52_0/boost/mpl/string.hpp
На нем, кстати, писали fizz buzz
Оставить комментарий
capxaH
Как известно компилятор умеет сам вычислять длину константной строки, т.е. такой код отлично скомпилитсяА можно ли на этапе компиляции посчитать количество различных букв в строке?