сделал удобную систему логирования, которая при возникновении ошибок выдает стек вызовов функций... в стеке в режиме дебага лежат строки с названием функций (__FUNCTION__), в режиме релиза лежат хеш-значения имен функций (для уменьшения размера релиза)... написал реализацию хеш-функции времени компиляции в виде constexpr-функции, но столкнулся с неожиданной проблемой... вот код: Код (Text): // Константификация значения хеша, тк бывает, что для constexpr // компилятор все же генерирует код времени выполнения template <uint32_t Const> struct Constantify { enum { Value = Const }; }; // Хеш-функция времени компиляции constexpr uint32_t Strhash(const char* Str) { /* реализация хеш-функции */ }; // Где-то в коде uint32_t hash1 = Constantify<Strhash("Test!")>::Value; // Нормально вычисляет хеш во времени компиляции uint32_t hash2 = Constantify<Strhash(__FUNCTION__)>::Value; // Ошибка компиляции сообщения ошибки: Код (Text): /main.cpp:6:76: in constexpr expansion of «Strhash(((const char*)(& __FUNCTION__)))» /main.cpp:6:77: ошибка: the value of «__FUNCTION__» is not usable in a constant expression /main.cpp:6:64: замечание: «__FUNCTION__» was not declared «constexpr» /main.cpp:6:77: замечание: in template argument for type «unsigned int» вообще мне это кажется странным, тк я не могу понять, чем с точки зрения компилятора __FUNCTION__ отличается от обычной константной строки... как пофиксить? ЗЫ gcc 4.6.1 если что...
Может быть Код (Text): const char * lpStr = __FUNCTION__; uint32_t hash2 = Constantify<Strhash(lpStr)>::Value; Компилятора нет ...
так не получится по все той же причине, очевидной компилятору, но не мне: Код (Text): ошибка: the value of «lpStr» is not usable in a constant expression
shchetinin Ну уж точно не так, т.к. это неконстантный указатель на константу. Попробуйте так: Код (Text): char const* const lpStr = __FUNCTION__; uint32_t hash2 = Constantify<Strhash(lpStr)>::Value;
нет, та же самая ошибка компиляции: Код (Text): ошибка: the value of «__FUNCTION__» is not usable in a constant expression я не понимаю, почему __FUNCTION__ не может быть использовано, как константное выражение...
Rel Попробуй сделать чтобы сама constexpr принимала не const char*, а выводила бы массив: Код (Text): template <int size> constexpr uint32_t Strhash(const char (&Str)[size]) { ... }
ну вообще при такой постановке задачи работает, но дело в том, что вычисление хеша происходит рекурсивно посимвольно... и я не пойму, как при такой постановке мне вызвать Strhash к следующему символу, например подсчет суммы значений символов в моем варианте был бы такой: Код (Text): constexpr uint32_t CountSum(const char* Str) { return (*Str) ? (*Str + CountSum(Str + 1)) : (0); } а как реализовать рекурсию с массивом в качестве параметра?
Rel Очевидно же: Код (Text): template <int size> constexpr uint32_t CountSum(const char (&Str)[size], int n = 0) { return n == size ? 0 : (Str[n] + CountSum(Str, n + 1)); } EDIT: фикс имен.
_DEN_ в constexpr функциях запрещена рекурсия. надо использовать разные шаблонные перегрузки http://forum.vingrad.ru/index.php?showtopic=322361&view=findpost&p=2299543
GoldFinch Удалено. Думаю... EDIT: Не, без нормального знания стандарта не могу сообразить А что, в C++09 нет какого-нибудь constexpr-ного for_each?
чего-чего? вообще constexpr имеет хоть какую-то ценность только благодаря рекурсии))) такой код собирается нормально и выдает ожидаемый результат: Код (Text): template <uint32_t N> constexpr uint32_t CountSum(const char (&Str)[N], uint32_t t = 0) { return Str[t] ? (Str[t] + CountSum(Str, t + 1)) : (0); } но, извиняйте... я в первый раз плохо проверил))) с __FUNCTION__ в качестве параметра выдает ту же самую ошибку...
Rel C++ - это такой язык, в котором вышеуказаный факт ни о чем не говорит. Скорее всего это значит, что компилятор не рассматривает __FUNCTION__ как литерную строку - для него это рантаймовое значение. Если это так, то тут будет баттхерт - с этим ничего не поделать.
у меня нет FDIS, однако в http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf написано если что-то поменялось - я только рад
Хреново то, что рекурсии через численные шаблонные параметры тут не катят - частичная специализация шаблонных функций запрещена, и как останавливать такие рекурсии - непонятно.
можно использовать как параметр шаблона константную строку с внешним связыванием. фактически будет использоваться её адрес. __FUNCTION__ явно не подходит
Код (Text): #include <iostream> template <int X, int Y> struct comb { static const int value = Y * comb<X, Y - 1>::value; }; template <int Y> struct comb<Y, Y> { static const int value = Y; }; template <int X, int Y> int get_comb() { assert(Y >= X); return comb<X, Y>::value; } int main() { std::cout << get_comb<1, 5>() << std::endl; }