代码之家  ›  专栏  ›  技术社区  ›  RaptorFactor

使用可变模板的编译时“字符串”操作

  •  8
  • RaptorFactor  · 技术社区  · 16 年前

    嘿,我现在正在尝试编写一个编译时字符串加密库(非常松散地使用“string”和“encryption”两个词)。

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

    但是,当我将字符扩展到静态数组中时,我不知道如何对字符执行操作。我只想对每个字符执行一个简单的操作(例如,“((c^0x12)^0x55)+1)”,其中c是字符)。

    朝着正确的方向努力将不胜感激。

    谢谢大家。

    2 回复  |  直到 16 年前
        1
  •  5
  •   Community Mohan Dere    9 年前

    如果您只想一次操作一个字符,那么很容易:

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

    CountArgs 是多余的(这就是 sizeof... 是为)而使用的 element-wise transformation of the elements in a parameter-pack


    要使转换依赖于以前的结果,一个选项是递归地使用字符,一次使用一个字符,并从中增量地构建一个新模板:

    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;
    };
    
        2
  •  1
  •   Motti    16 年前

    如果我理解了您要正确执行的操作(实际上是在编译时创建一个数组),我认为可变模板是不够的,您必须等待 constexpr

    但是,如果您不需要实际的数组,而可以在使用类似于 tuple get<I> 然后它是可能的(然后你可以建立一个 char 运行时的数组)。