2010-08-16 7 views
8

Hola a todos, actualmente estoy tratando de escribir un cifrado de cadena en tiempo de compilación (utilizando las palabras 'cadena' y 'encriptación' bastante libremente) lib.Manipulación 'cadena' en tiempo de compilación con plantillas variables

Lo que tengo hasta ahora es la siguiente:

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

sin embargo no puedo encontrar la manera de realizar operaciones en los personajes como lo expandirlas en la matriz estática. Me gustaría ejecutar una operación simple en cada carácter (por ejemplo, '((c^0x12)^0x55) + 1)' donde c es el personaje).

Un empujón en la dirección correcta sería muy apreciado.

Gracias a todos.

+0

Podría dar una ejemplo de cómo le gustaría usar esto con las funciones dadas arriba? – David

+0

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

Respuesta

4

Si lo que desea es operar en un carácter a la vez que es fácil:

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

Tenga en cuenta que CountArgs es redundante (eso es lo que es para sizeof...) y que este utiliza element-wise transformation of the elements in a parameter-pack.


Para realizar la transformación depende de los resultados anteriores, una opción sería consumir los caracteres de forma recursiva, uno a la vez, y de manera progresiva construcción de una nueva plantilla a partir de que:

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

Gracias. Eventualmente, sin embargo, quería expandirlo para operar usando un algoritmo más complejo (es decir,utilizando el resultado de la operación anterior como 'semilla' para el 'cifrado' del siguiente personaje). ¿Es eso posible, o tendré que seguir con una solución de un solo personaje? EDITAR: ¡Acaba de probar su solución por cierto y funcionó! Todavía tiene curiosidad sobre si es posible implementarlo usando un algoritmo más complejo. – RaptorFactor

+0

@Raptor: Hm, pensando en ello. –

+0

Es un problema divertido.^_^ – RaptorFactor

1

Si entiendo lo que quiere hacer correctamente (en realidad creo una matriz en tiempo de compilación) creo que las plantillas variadas no son suficientes y tendrá que esperar constexpr.

Sin embargo, si usted no necesita una matriz real y en su lugar se puede comprometer en el uso de algo parecido a tuple 's get<I> entonces es posible (a continuación, puede construir una matriz char en tiempo de ejecución).

+0

Ah, por supuesto, no pensé en eso. Sí, construir la cadena en tiempo de ejecución a partir de caracteres 'encriptados' individualmente es una solución aceptable por el momento. Siempre que la manipulación real de los caracteres ocurra en el momento de la compilación, será genial. Gracias! – RaptorFactor

+0

Uf, esto es tan difícil de entender al principio. No tengo idea de cómo las personas pueden incluso mantener ciertas libs pesadas en TMP (¡mirándote Boost!: P). – RaptorFactor

+0

¿Podría proporcionar un ejemplo de cómo construiría la cadena en tiempo de ejecución? He agregado la función 'get' y la he puesto a trabajar carácter por carácter, pero como es una plantilla, no puedo simplemente ponerla en un bucle y construir la cadena en tiempo de ejecución de esa manera. Estoy confundido acerca de cómo se supone que debo hacerlo sin hacerlo manualmente (por ejemplo, llamar manualmente a get <> para cada personaje y agregarlo manualmente a mi cadena). Agradecería mucho otro empujón en la dirección correcta, soy bastante nuevo en todo esto. Gracias. :) – RaptorFactor

Cuestiones relacionadas