从动态索引中选择一个 constexpr 索引

Selecting a constexpr index from a dynamic index

我有 C++ 代码调用一些 SSE/AVX 函数获取立即索引值(例如 int _mm_extract_epi16 (__m128i a, int imm8))。问题是,我在编译时不知道索引值,所以我必须做一个动态的 intconstexpr int 转换:

template <int index>
auto extract(__m128i a) noexcept
{
    static_assert(index < 8, "index must be less than 8");
    return _mm_extract_epi16(a, index);
}

auto extract(const __m128i a, const int index) noexcept
{
    switch (index) {
        case 0:  return extract<0>(a);
        case 1:  return extract<1>(a);
        case 2:  return extract<2>(a);
        case 3:  return extract<3>(a);
        case 4:  return extract<4>(a);
        case 5:  return extract<5>(a);
        case 6:  return extract<6>(a);
        case 7:  return extract<7>(a);
        default: return extract<7>(a);
    }
}

我正在将我的代码库升级到 AVX2 和 AVX-512(因此将案例数量分别扩展到 16 和 32),并开始想知道是否有更好的方法来做到这一点?或者至少是一种避免输入太多的方法?

template <std::size_t... Is>
auto extract(const __m128i a, const int index, std::index_sequence<Is...>) noexcept
{
    if(index < 8 && index >= 0)
    {
        decltype(extract<0>(a)) r;
        int unused[] = {(index == Is ? (r = extract<Is>(a), 0) : 0)...};
        (void)unused;
        return r;
    }
    else
        return extract<7>(a);
}

auto extract(const __m128i a, const int index) noexcept
{
    return extract(a, index, std::make_index_sequence<8>{});
}

或者您可以改用 C++17 中的折叠表达式。这编译为 same thing 作为开关。

但是我会争辩说,在这种情况下,由于您所保存的只是一些输入,因此只需复制和粘贴就可以了。读写更简单