Hey all, I'm currently trying to write a compile-time string encryption (using the words 'string' and 'encryption' quite loosely) lib.
What I have so far is as follows:
// 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...
};
However I can't figure out how to perform operations on the characters as I expand them into the static array. I'd just like to execute a simple operation on each character (e.g. '(((c ^ 0x12) ^ 0x55) + 1)' where c is the character).
A shove in the right direction would be greatly appreciated.
Thanks all.
If you just want to operate on one character at a time its easy:
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"
}
Note that CountArgs
is redundant (that's what sizeof...
is for) and that this uses element-wise transformation of the elements in a parameter-pack.
To make the transformation dependent on previous results, one option would be to consume the characters recursively, one at a time, and incrementally build a new template from that:
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;
};
If I understand what you want to do correctly (actually create an array at compile time) I think variadic templates aren't enough and you'll have to wait for constexpr
.
If however you don't need an actual array and can instead compromise on using something akin to tuple
's get<I>
then it's possible (you can then build a char
array at runtime).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With