Compile-time 'String' Manipulation with Variadic Templates

后端 未结 2 1290
忘掉有多难
忘掉有多难 2020-12-30 10:04

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

相关标签:
2条回答
  • 2020-12-30 10:47

    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).

    0 讨论(0)
  • 2020-12-30 11:08

    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;
    };
    
    0 讨论(0)
提交回复
热议问题