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

在模板元编程中使用列表类型

  •  3
  • doron  · 技术社区  · 6 年前

    我有一个编码方案,我使用以下规则转换数字[0-9]。

    0—3
    1—7
    2—2
    3—4
    4—1
    5 - 8
    6—9
    7—0
    8—5
    9—6

    因此,我可以使用以下数组进行正向查找
    int forward[] = { 3,7,2,4,1,8,9,0,5,6}
    哪里 forward[n] 是n的编码。 类似地,以下是反向查找
    int inverse{ 7,4,2,0,3,8,9,1,5,6};
    其中'inverse[n]将解码n

    反向数组可以在运行时从正向数组轻松创建,但理想情况下,我希望在编译时创建它。鉴于模板元编程是一种功能性语言,我首先使用以下语言在Haskell中实现了所有内容:

    pos :: [Int] -> Int -> Int
    pos lst x = 
        let 
            pos'::[Int] -> Int -> Int -> Int
            pos' (l:lst) x acc
                | l == x = acc
                | lst == [] = -1
                | otherwise = pos' lst x (acc + 1)
        in
            pos' lst x 0
    
    inverse ::[Int] -> [Int]
    inverse lst =
        let
            inverse'::[Int] -> Int -> [Int]
            inverse' l c 
                | c == 10 = []
                | otherwise = pos l c : inverse' l (c + 1)
        in
            inverse' lst 0 
    

    我设法实现了 pos 在C++模板中使用元编程:

    #include <iostream>
    
    static int nums[] = {3,7,2,4,1,8,9,0,5,6};
    
    template <int...>
    struct pos_;
    
    template <int Find, int N, int Arr0, int... Arr>
    struct pos_<Find,N, Arr0, Arr...> {
        static constexpr int value = pos_<Find, N+1, Arr...>::value;
    };
    
    template <int Find, int N, int... Arr>
    struct pos_<Find ,N, Find, Arr...> {
        static constexpr int value = N;
    };
    
    template <int Find,int N>
    struct pos_<Find ,N> {
        static constexpr int value = -1;
    };
    
    template <int Find, int... Arr>
    struct pos {
        static constexpr int value = pos_<Find,0, Arr...>::value;
    };
    
    int main()
    {
        std::cout << "the positions are ";
    
        std::cout << pos<3, 3,7,2,4,1,8,9,0,5,6>::value << std::endl;
    }
    

    然而,我在将数组转换为参数包时遇到了困难,而且在实现反向时,我无法分配 value 参数包。

    在模板元编程中使用列表的最佳方法是什么?

    对于上下文,在查看base64编码时,这个问题浮现在脑海中,我想知道是否有一种方法可以在编译时生成反向编码。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Dan M.    6 年前

    constexpr

    template<size_t N>
    constexpr std::array<int, N> inverse(const std::array<int, N> &a) {
        std::array<int, N> inv{};
        for (int i = 0; i < N; ++i) {
            inv[a[i]] = i;
        }
        return inv;
    }
    

    https://godbolt.org/g/uECeie