1

我现在有一些看起来像这样的代码:

#define ______ 0x0000
static const uint16_t plane0[256] = {
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
    0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
    0x0058, 0x0059, 0x005A, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, 0x039C, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ...
};
#undef ______

uint16_t caseup(uint16_t wc)
{
    return (plane0[wc] == 0x0000) ? wc : plane0[wc];
}

我真的很想caseup用一个简单的return plane0[wc]. 从总体上看,额外的比较和分支可能不会很昂贵,但如果我们去掉它,代码肯定会更有效。

但我不想重写表格。甚至不使用工具来重写它——我不希望我们的案例映射表被很多垃圾的十六进制值弄得乱七八糟。我希望该表保持大部分原始宏观化,仅在实际需要非身份案例映射的地方使用十六进制值。

在 C++11 中最干净的方法是什么?

4

3 回答 3

0

我想过这个:

template<int N>
struct PlaneMapping {
    uint16_t i;
    uint16_t data[N];

    template<typename... Args>
    constexpr PlaneMapping(Args... a) : i(0), data { uint16_t(a ? (i++,a) : i++)... }
    {}
};

static const PlaneMapping<256> plane0(
    ______, ______, ______, ______, ______, ______, ______, ______,
    ______, ______, ______, ______, ______, ______, ______, ______,
    ...
);

uint16_t caseup(uint16_t wc)
{
    return plane0.data[wc];
}

我猜这是相当干净的,但所有这些i++s 都很丑陋,你必须通过-O1或更好,然后它才能一直编译为静态数据,而不是从_main. 有更清洁的解决方案吗?

于 2013-11-05T01:26:10.893 回答
0
uint16_t caseup(uint16_t wc)
{
    static const std::array<uint16_t, 256> plane0Map = [&]
    {
        std::array<uint16_t, 256> mapping;

        for(size_t i = 0; i < 256; ++i)
            mapping[i] = plane0[i] == 0 ? i : plane0[i];

        return mapping;
    }();

    return plane0Map[wc];
}
于 2013-11-05T02:35:46.840 回答
0

在这种情况下,我建议不要执行此类优化,除非分析表明这是一个瓶颈。就像你说的,你喜欢桌子的干净(更容易阅读/维护),如果性能在这里不重要,你想保留这些属性。

另一方面,有一种方法可以用时间交换空间:制作另一个数组副本,并转换值;您只需要执行一次复制/翻译,并且在 caseup() 中查找此新数组而无需分支。原始阵列没有更改,仍然干净且易于更改。

static const uint16_t plane0lookup[256];
for(uint16_t i = 0; i<256; ++i)
{
    plane0lookup[i] = (plane0[wc] == 0x0000) ? i : plane0[wc];
}

uint16_t caseup(uint16_t wc)
{
    return plane0lookup[wc];
}
于 2013-11-05T02:02:39.427 回答