以C ++元编程风格实现RLE算法

时间:2019-03-04 01:51:10

标签: c++ templates recursion template-meta-programming

我已经为RLE(游程长度编码)实现了一种简单的递归算法。

代码:

#include <iostream>
using namespace std;

template <size_t N>
struct RLE {
    static size_t cnt;

    static void Compress(char const p[]) {                
        // Check current char with next char. If they are not same then print the current character and its count. Then reset the counter to 0 for next itetation.
        if (!(*p == *(p + 1))) {
            cout << cnt << *p;
            cnt = 0;
        }
        // Call the function again with new character
        RLE<N - 1>::Compress(p + 1);
    }
};

template <size_t N>
size_t RLE<N>::cnt = 1 + RLE<N - 1>::cnt;

template <>
struct RLE<0> {
    static size_t cnt;
    static void Compress(char const[]) {
    }
};;

//template<>  // On uncomenting this like why do I get a error "extraneous template<>, in declaration of variable cnt."
size_t RLE<0>::cnt = 0;

int main(void) {
    char const str[]{"mmatsss"};

    // -1 since sizeof includes terminating null char.
    RLE<sizeof(str) - 1>::Compress(str);
}

对于像“ mmatsss”这样的输入,预期的输出是“ 2m1a1t3s”,但是我得到的是“ 1m1a1t1s”,即代码仅打印该组的第一个字符。我无法找出代码中的错误。有人可以看看吗,并帮助我了解我在这里做错了什么。

1 个答案:

答案 0 :(得分:1)

  

我无法弄清代码中的错误,可以请人看看它,并帮助我了解我在这里做错什么。

问题是您按如下方式初始化静态成员cnt

template <size_t N>
size_t RLE<N>::cnt = 1 + RLE<N - 1>::cnt;

size_t RLE<0>::cnt = 0;

因此,当编译器使用初始化的cnt == N值(g ++情况)时,您得到RLE<N - 1>::cnt,当cnt == 1时,N > 0,而编译器对{{1 }}(lang语)。

我不知道谁是对的,但重点是你写作时

RLE<N - 1>::cnt

您在 cout << cnt << *p; cnt = 0; 中打印cnt –根据情况使用RLE<N>N –并且将{{ 1}}。

但是当您将1中的cnt设置为零时,RLE<N>中的cnt保持不变(因此RLE<N>cnt,视情况而定。)

我在您的代码中看不到太多元编程,但在我看来,可能的更正是将所有RLE<N-1>都设置为1

N-1

并将1中的cnt设置为template <size_t N> size_t RLE<N>::cnt = 1; size_t RLE<0>::cnt = 1;

RNE<N-1>::cnt

但是,坦率地说,我更喜欢您的原始(而非元编程)代码。