Манипуляция строкой во время компиляции с помощью шаблонов Variadic - PullRequest
8 голосов
/ 16 августа 2010

Привет всем, в настоящее время я пытаюсь написать строковое шифрование во время компиляции (используя слова 'string' и 'encryption' довольно свободно) lib.

То, что я пока имею, таково:

// Cacluate narrow string length at compile-time
template <char... ArgsT>
struct CountArgs
{
 template <char... ArgsInnerT> struct Counter;

 template <char Cur, char... Tail>
 struct Counter<Cur, Tail...>
 {
  static unsigned long const Value = Counter<Tail...>::Value + 1;
 };

 template <char Cur>
 struct Counter<Cur>
 {
  static unsigned long const Value = 1;
 };

 static unsigned long const Value = Counter<ArgsT...>::Value;
};

// 'Encrypt' narrow string at compile-time
template <char... Chars>
struct EncryptCharsA
{
 static const char Value[CountArgs<Chars...>::Value + 1];
};

template<char... Chars>
char const EncryptCharsA<Chars...>::Value[CountArgs<Chars...>::Value + 1] =
{
 Chars...
};

Однако я не могу понять, как выполнять операции над символами, когда я расширяю их в статический массив.Я просто хотел бы выполнить простую операцию с каждым символом (например, '(((c ^ 0x12) ^ 0x55) + 1)', где c - символ).

Пуш в правильном направлении будетс благодарностью.

Спасибо всем.

Ответы [ 2 ]

4 голосов
/ 16 августа 2010

Если вы просто хотите работать с одним символом за раз, это просто:

template<char c> struct add_three {
    enum { value = c+3 };
};

template <char... Chars> struct EncryptCharsA {
    static const char value[sizeof...(Chars) + 1];
};

template<char... Chars>
char const EncryptCharsA<Chars...>::value[sizeof...(Chars) + 1] = {
    add_three<Chars>::value...
};

int main() {   
    std::cout << EncryptCharsA<'A','B','C'>::value << std::endl;
    // prints "DEF"
}

Обратите внимание, что CountArgs является избыточным (для этого sizeof...) и использует поэлементное преобразование элементов в пакете параметров .


Чтобы сделать преобразование зависимым от предыдущих результатов, одним из вариантов будет рекурсивное использование символов, по одному за раз, иПостроить новый шаблон из этого:

template<char... P> struct StringBuilder {
    template<char C> struct add_char {
        typedef StringBuilder<P..., C> type;
    };

    static const char value[sizeof...(P)+1];
};

template<char... P> const char StringBuilder<P...>::value[sizeof...(P)+1] = {
    P...
};

template<class B, char...> struct EncryptImpl;

template<class B, char Seed, char Head, char... Tail> 
struct EncryptImpl<B, Seed, Head, Tail...> {
    static const char next = Head + Seed; // or whatever
    typedef typename EncryptImpl<
        typename B::template add_char<next>::type,
        next, Tail...
    >::type type;
};

template<class B, char Seed> struct EncryptImpl<B, Seed> {
    typedef B type;
};

template<char... P> struct Encrypt {
    typedef typename EncryptImpl<StringBuilder<>, 0, P...>::type type;
};
1 голос
/ 16 августа 2010

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

Если, однако, вам не нужен реальный массив, и вы вместо этого можете пойти на компромисс с использованием чего-то, похожего на tuple s get<I>, тогда это возможно (вы можете построить массив char во время выполнения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...