2010-08-16 7 views
8

Salut à tous, J'essaye actuellement d'écrire un chiffrement de chaîne à la compilation (en utilisant les mots 'string' et 'encryption' assez librement) lib.Manipulation 'String' au moment de la compilation avec des modèles variadiques

Ce que j'est jusqu'à présent comme suit:

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

Cependant je ne peux pas comprendre comment effectuer des opérations sur les personnages que je les développer dans le tableau statique. Je voudrais juste exécuter une opération simple sur chaque caractère (par exemple '(((c^0x12)^0x55) + 1)' où c est le caractère).

Une poussée dans la bonne direction serait grandement appréciée.

Merci à tous.

+0

Pourriez-vous donner un exemple sur la façon dont vous souhaitez utiliser cela avec les fonctions indiquées ci-dessus? – David

+0

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

Répondre

4

Si vous voulez juste faire fonctionner sur un caractère à la fois il est facile:

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

Notez que CountArgs est redondant (c'est ce que sizeof... est pour) et que celui-ci utilise element-wise transformation of the elements in a parameter-pack.


Pour rendre la transformation dépendante des résultats précédents, une option serait de consommer les caractères récursive, un à la fois, et construire progressivement un nouveau modèle de celui:

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

Merci. Finalement, cependant, je voulais l'étendre pour fonctionner en utilisant un algorithme plus complexe (c.-à-d.utiliser le résultat de l'opération précédente comme une «graine» pour le «chiffrement» du caractère suivant). Est-ce possible ou devrais-je m'en tenir à une solution à un seul caractère? EDIT: Juste testé votre solution btw et cela a fonctionné! Toujours curieux de savoir s'il est possible de l'implémenter en utilisant un algorithme plus complexe. – RaptorFactor

+0

@Raptor: Hm, j'y pense. –

+0

C'est un problème amusant.^_^ – RaptorFactor

1

Si je comprends ce que vous voulez faire correctement (en fait créer un tableau au moment de la compilation) Je pense que les modèles variés ne suffisent pas et vous devrez attendre constexpr.

Si toutefois vous n'avez pas besoin d'un tableau réel et peut compromettre la place sur l'utilisation de quelque chose de semblable à l » get<I>tuple alors il est possible (vous pouvez construire un tableau char lors de l'exécution).

+0

Ah bien sûr, je n'y ai pas pensé. Oui, la construction de la chaîne à l'exécution à partir de caractères «cryptés» individuellement est une solution acceptable pour le moment. Tant que la manipulation réelle des personnages arrive au moment de la compilation, ce sera génial. Merci! – RaptorFactor

+0

Ugh, ce truc est si difficile à comprendre au début. Je n'ai aucune idée de comment les gens peuvent même maintenir certaines librairies lourdes TMP (en regardant Boost!: P). – RaptorFactor

+0

Pourriez-vous s'il vous plaît fournir un exemple de la façon dont je construirais la chaîne à l'exécution? J'ai ajouté la fonction 'get' et je l'ai fait caractère par caractère, mais comme il s'agit d'un modèle, je ne peux pas le lancer en boucle et construire la chaîne à l'exécution de cette façon. Je suis confus quant à la façon dont je suis censé le faire à court de le faire complètement manuellement (par exemple en appelant manuellement get <> pour chaque caractère et en l'ajoutant manuellement à ma chaîne). J'apprécierais énormément une autre poussée dans la bonne direction, je suis assez nouveau à tout cela. Merci. :) – RaptorFactor

Questions connexes