简体   繁体   English

可变参数模板的编译时“字符串”操作

[英]Compile-time 'String' Manipulation with Variadic Templates

Hey all, I'm currently trying to write a compile-time string encryption (using the words 'string' and 'encryption' quite loosely) lib. 大家好,我目前正在尝试编写一个编译时字符串加密(非常宽松地使用单词“ string”和“ encryption”)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 (eg '(((c ^ 0x12) ^ 0x55) + 1)' where c is the character). 我只想对每个字符执行一个简单的操作(例如'((((c ^ 0x12)^ 0x55)+ 1)'其中c是字符)。

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 . 请注意, CountArgs是多余的(那是sizeof...目的),并且它使用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 . 如果我了解您要正确执行的操作(实际上是在编译时创建一个数组),我认为可变参数模板还不够,您必须等待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). 但是,如果您不需要实际的数组,而是可以折衷使用类似于tupleget<I>则有可能(然后可以在运行时构建char数组)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM