2010-08-16 20 views
8

Hej wszystkim, obecnie próbuję napisać szyfrowanie ciągów kompilacji (używając luźno słów "string" i "encryption") lib.Skompilowanie manipulacji "ciągiem" przy użyciu szablonów zmiennych

Co mam tak daleko jest w następujący sposób:

// 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... 
}; 

Jednak nie mogę dowiedzieć się, jak wykonywać operacje na bohaterów jak rozwinąć je w statycznej tablicy. Chciałbym wykonać prostą operację na każdym znaku (np. ((((C^0x12)^0x55) + 1) 'gdzie c jest znakiem).

Pchnięcie we właściwym kierunku zostanie bardzo docenione.

Dzięki wszystkim.

+0

mógłbyś dać przykład, w jaki sposób chciałbyś użyć tego z funkcjami podanymi powyżej? – David

+0

char const * const pFooEnc = EncryptCharsA <'F','o','o'> :: Wartość; – RaptorFactor

Odpowiedz

4

Jeśli chcesz po prostu działają na jeden znak w czasie jego krótkiego:

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" 
} 

Zauważ, że CountArgs jest zbędny (to co jest dla sizeof...) i że ta wykorzystuje element-wise transformation of the elements in a parameter-pack.


Aby transformacja zależna od poprzednich wyników, jednym rozwiązaniem byłoby spożywać znaki rekurencyjnie, po jednym na raz, i stopniowo budować nowy szablon, który:

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; 
}; 
+0

Dzięki. Ostatecznie jednak chciałem go rozszerzyć, aby działał przy użyciu bardziej złożonego algorytmu (tj.użycie wyniku poprzedniej operacji jako "nasiona" do "szyfrowania" następnego znaku). Czy to nawet możliwe, czy będę musiał trzymać się rozwiązania z jednym znakiem? EDYTOWANIE: Właśnie przetestowałem twoje rozwiązanie i zadziałało! Wciąż zastanawiasz się, czy możliwe jest zaimplementowanie go przy użyciu bardziej złożonego algorytmu. – RaptorFactor

+0

@Raptor: Hm, myślę o tym. –

+0

To jest zabawny problem.^_^ – RaptorFactor

1

Jeśli rozumiem, co chcesz zrobić poprawnie (faktycznie utworzyć tablicę w czasie kompilacji) Myślę, że szablony variadyczne nie są wystarczające i będziesz musiał czekać na constexpr.

Jeśli jednak nie trzeba rzeczywisty układ i może zamiast rezygnować z pomocą czegoś w rodzaju tuple „s get<I> to jest możliwe (można następnie zbudować char tablicy w czasie wykonywania).

+0

Ach, oczywiście, nie myślałem o tym. Tak, budowanie łańcucha w czasie wykonywania z pojedynczych "zaszyfrowanych" znaków jest na razie możliwym do przyjęcia rozwiązaniem. Dopóki faktyczna manipulacja postaciami nastąpi w czasie kompilacji, to będzie świetnie. Dzięki! – RaptorFactor

+0

Ugh, te rzeczy są tak ciężko na początku. Nie mam pojęcia, jak ludzie mogą nawet utrzymywać pewne ciężkie biblioteki TMP (patrząc na ciebie, Boost !: P). – RaptorFactor

+0

Proszę podać przykład, w jaki sposób zbudowałem ciąg w czasie wykonywania? Dodałem funkcję "get" i zacząłem pracować na zasadzie znak po znaku, ale ponieważ jest to szablon, nie mogę po prostu rzucić go w pętlę i skompilować ciąg w ten sposób. Jestem zdezorientowany tym, jak powinienem zrobić to prawie całkowicie ręcznie (i.g. ręcznie wywołując get <> dla każdej postaci i ręcznie dodając ją do mojego ciągu znaków). Byłbym bardzo wdzięczny za kolejny krok w dobrym kierunku, jestem całkiem nowy w tym wszystkim. Dzięki. :) – RaptorFactor

Powiązane problemy