Как стать автором
Обновить

Комментарии 47

Действительно ненормальное программирование. Не позавидую тому, кому прийдется сопровождать после Вас такой код. А вообще идея интересная.
Никому не нужно будет сопровождать, так как проект личный и делался в целях самообразования и поиска нестандартных решений. Так же хотелось прощупать возможности кимпилеров по оптимизации.
Реализация понравилась. А вот сама идея, не очень. Понятно, что где то в коде будет кусок кода парсящий какую-нибудь dll-ку на предмет выдергивания имен из IMAGE_IMPORT_DESCRIPTOR с последующей передачей этих строк в ваш хеш. А перед всем этим действом LoadLibrayA (some_name). Так что bp kernel32!LoadLibraryA ".printf «from %x library = <%ma>\n», poi(esp), poi(esp+4);g" Очень быстро выводит на след. Поэтому на всякий случай скажу вот, что добавьте сюда самостоятельный парсинг PE заголовка и когда вытащите адрес интересующей вас функции делайте jmp не на нее, а скажем на address_of_function + 5. Вот это уже будет веселее. Но все равно понравилось.
НЛО прилетело и опубликовало эту надпись здесь
Согласен с вами, но иногда хочется чего-то необычного…
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
С++ не имеет встроенных средств написания чисел в двоичном виде.

а
 int myBinaryNumber = 0b0110110; 
уже отменили? Или я что-то неправильно помню?
Неправильно помните )
0b0110110 — это в новой Java (JDK 7).
А это тогда как объясните?
#include <iostream>
using namespace std;
int main()
{
        int num = 0b0010010;
        cout << num << endl;
        return 0;
}


beaver@gentoo /home/beaver/1 $ g++ 1.cpp -o 1
beaver@gentoo /home/beaver/1 $ ./1
18
НЛО прилетело и опубликовало эту надпись здесь
Ну да, согласен. Сейчас с помощью товарища проверил, в cl.exe такого нет. Но это не повод городить то, что написал автор.
hash_text очень странный, какой в нем смысл? Если функция runtime. Почему нельзя было использовать тернарный оператор и enum или static const unsigned int переменную, например как сделано в code_text для count. Тогда будет compile-time. А для двоичных чисел просто изврат какой-то. Вот реальный рабочий пример, без извратов и с минимумом кода.

template
struct binary
{
static const int value = (N % 10) + 2 * binary< N / 10 >::value;
};

template
struct binary
{
static const int value = 0;
};

использование

binary::value;

и в результате полнейший compile-time.

На будущее я бы посоветовал покопать в сторону мета-программирования на сях.
Почитать
Джеф Элджер C++ for Real Programmers (есть на русском)
Андреq Александреску Modern C++ Design (есть на русском)
David Abrahams and Aleksey Gurtovoy, C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond (на русском не видел).
А уже затем заниматься ненормальным программированием.
Блин, вырезались знаки больше-меньше, код

template<int N>
struct binary
{
static const int value = (N % 10) + 2 * binary<N / 10>::value;
};

template<>
struct binary<0>
{
static const int value = 0;
};

использовать
binary<11101111>::value
binary<00101001> работать не будет, т.к. восьмеричное. Но идея, конечно, лучше чем куча ифов.
нет, ведущие нолики не указывать и будет работать. Или делить на 8 и писать всегда ведущий 0.
Такое тоже имеет право на жизнь и я об этом знаю, вопрос в том сколько разрядов поместится? В вашем примере малавато будет, в моем примере намного больше, хотя и выглядит похуже, но цель была не в этом
Ну да, минус только в разрядах, но для большинства задач хватает небольшого кол-ва, можно использовать 64 битный тип, будет побольше разрядов. Но в данном примере полный compile-time, а для run-time можно просто строку использовать.
На худой конец можно было хотябы избавится от run-time, а синтаксис оставить подобным, что-то типа.

Что-то типа для одного байта, расширять можно до бесконечности

#include <iostream>

// Основной тип для вычисления, здесь пробегаем рекурсивно число.
template<
int c01 = -1, int c02 = -1, int c03 = -1, int c04 = -1,
int c05 = -1, int c06 = -1, int c07 = -1, int c08 = -1
>
struct bin_to_dec
{
enum {value = bin_to_dec<-1, c01, c02, c03, c04, c05, c06, c07>::value << 1 | c08};
};

// Тип для ротации вправо, в случае, если указаны не все биты.
template<
int c01, int c02, int c03, int c04, int c05, int c06, int c07
>
struct bin_to_dec<c01, c02, c03, c04, c05, c06, c07, -1>
{
enum {value = bin_to_dec<-1, c01, c02, c03, c04, c05, c06, c07>::value};
};

// тип для завершения вычислений, для завершения рекурсии первого типа
template<>
struct bin_to_dec<-1, -1, -1, -1, -1, -1, -1, -1>
{
enum {value = 0};
};

int main(int argc, char *argv[])
{
std::cout << bin_to_dec<1,0,1>::value << std::endl;
std::cout << bin_to_dec<0,1,1,0,0,1,0,1>::value << std::endl;
return 0;
}

В результате мы получили compile-time, нужно только подумать.
А где вы там увидели run-time? Конечный результат будет в виде одного числа, т. е. чистый compile-time.
run-time увидел в функции static unsigned int dec(), compile-time будет в случае, если компилятор решит соптимизировать, а иначе будет чистейший run-time.
миль пардон, но относительно бинарных чисел это не изврат. Чисто технически понимание дизасма в первом случае займет чуть больше времени, чем какой-нибудь классический алгоритм назначение, которого понятно сразу.
Ну здесь требуется понимание работы шаблонов, а это думаю не сложно, простейший рекурсивный шаблон. Если же пользоваться шаблонами и не знать как они работают, это не есть хорошо. Да и существуют комментарии, к хитрому коду пишу всегда, если наоборот не требуется запутать.
Мы судим с несколько разных точек зрения. Вы, судите о том на сколько удачно поставленная задача решается инструментарием языка C++. Я сужу о том насколько
эффективно решена задача, а решена она прямо скажем слабенько. Но судя по всему человек этим занимался явно первый раз в жизни. Так что на мой взгляд все не так уж и плохо. А вот относительно темплейтов соглашусь. На самом деле — это просто впустую потраченное автором время. На уровне дизасма никаких темплейтов попросту не существует.
Ну про первый раз с шаблонами вы явно загнули, я с ними работаю с момента их появления на С++. А насчет дизасма, вы не совсем поняли, цель была в формировании хэшей во время компиляции, естественно никаких шаблонов в результирующем exe не будет, будут только хеши для сравнения и больше ничего не требовалось. Также и со строками, будет только кодированный текст сформированный самим компилятором.
Ну хэши будут во время компиляции в одном случае, если этого захочет оптимизатор, а если не захочет, будет run-time код. Для того, чтобы был 100% compile-time нужно избавится от всех методов. А в вашем случае, если получится run-time, то будет совсем жуткое кол-во кода.
нет, ведущие нолики не указывать и будет работать.
Думаю, что с появлением C++0x ваш можно будет реализовать более элегантно. Я бы советовал посмотреть в сторону variadic templates и user-defined literals. Вот пример из статьи C++0x в википедии:
    template<char...> OutputType operator "" _suffix();
    OutputType some_variable = 1234_suffix;   //  operator "" _suffix<'1', '2', '3', '4'>()

С новым стандартом пока сильно не разбирался, но когда уже окончательно утвердять и появится его полная поддержка, то буду копать. Есть еще много задач которые хотелось бы решать с помощью шаблонов.
Добавляю в избранное только из-за комментов, в том числе будущих.
Добавлю еще и я свой вариант для вычисления в compile-time двоичных литералов:
template <int N>
int parse_binary(const char *s)
{
    int ret = 0;
    for (size_t i = 0; i < N; ++i) {
        ret = (ret << 1) + (s[i] == '0'? 0 : 1);
    }
    return ret;
}

template <int N>
int parse_binary(const char (&s)[N])
{
    return parse_binary<N-1>(static_cast<const char *>(s));
}

#define BIN(b) parse_binary(#b)

int main(int argc, char* argv[])
{
    return BIN(11000000); // mov eax, 192
}
Простите, а где здесь compile-time? Я так понимаю compilte-time тут будет только если этого захочет оптимизатор, а иначе будет run-time? Или я ошибаюсь?
Все зависит от компилятора и длины исходного кода, но в большинстве случаев всегда будет compile-time, но если код слишком большой (как в примере кодирования строк, а у меня в реальном проекте он раза в два больше), то иногда надо увеличить в параметрах длину инлайн функций, как мне пришлось сделать в gcc, а OpenWatcom все чудесно проглотил без проблем
Да, от оптимизации зависит.
Но, как уже рядом ответили, в большинстве случаев такая оптимизация срабатывает.
Простите, но зачем шаблоны, когда гораздо проще и красивее было бы сделать то же самое макросом?
Макросами не будет красиво и наврядли с помощью них такое возможно сделать. Да и макросы являются наследием С, и для С++ с его шаблонами их не рекомендуют применять. Хотя я может чего-то не знаю, если вы считаете что макросами можно такое сделать, то приведите пример.
Во-первых, Вы недооцениваете мощь макросов, в них это реализуемо :) Реализовывать именно этот алгоритм лень из-за того, что получится длинновото, но получится что-то в духе:
#define HASH(s) s[0]? ... : ...

где ... будут достаточно длинными :)

Во-вторых, если инструмент есть, если он работает, почему его нужно сознательно игнорировать?
Дело в том что наврядли с помощью макросов можно сделать такие вычисления во время компиляции (макросы это ведь подстановки, а шаблоны это уже вычисления). Интересно как можно с помощью макросов определить конец строки? Причем так чтобы дальше не было вычислений.
Да Вы что? Компилятор давно разучился вычислять константы во время компиляции? o_O
В общем, не читайте тех газет, которые говорят, что макросы — фуфло. Макросы — сила, пусть они и послабее шаблонов будут. Я вот когда мне не хватало возможностей препроцессора cpp (cpp != c++, это название самой программы-препроцессора C), подключил m4, который, кстати, является полноценным языком программирования.
Я не считаю макросы фуфлом, просто они, как вы сказали, слабее шаблонов, я еще добавлю — намного слабее. Да и выглядят макросы не совсем хорошо по сравнением с шаблонами. Сейчас попробовал с помощью макросов сделать вычисление хэша, не получилось, мало того, код выглядит намного ужасней и непонятней. Попробуйте сами хотя бы для 4-х символов и при этом учтите, что может передаваться строка меньшего размера.
Достаточно написать ещё несколько вспомогательных макросов, либо же нагенерить макрос скриптом ;)

С третьей стороны, если бы передо мной стояла такая задача, я бы просто считал нужные значения отдельным скриптом-препроцессором.
кстати, насчёт конца строки — можно просто проверить символ на ноль.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации