c++ - 从动态索引中选择一个 constexpr 索引

标签 c++ c++11 c++14 constexpr

我有 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作为开关。

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

关于c++ - 从动态索引中选择一个 constexpr 索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56303429/

相关文章:

c++ - 模板化 vs const 非模板化 vector 没有已知的转换

C++ lambda 表达式无法编译

c++ - Lambda 捕获 C++14

c++ - 使用带有 clang++ 而不是 g++ 的 std::acos 的 Constexpr 编译错误

c++ - 是否可以覆盖运算符?

c++ - 精确返回 double

c++ - 为什么 “cast from ‘X*’ 到 ‘Y’ 失去精度”是一个硬错误,什么是遗留代码的合适修复

c++ - 数组拆分为头文件和源文件

c++ - 从 Matlab 连接到本地服务器

c++ - 为什么 GNU make 忽略或更改我的 g++ 选项(在命令部分)?