c++ - 用于重新排序无符号整数的 Constexpr 变量模板

标签 c++ templates c++17 variadic-templates c++20

我正在使用首先发送最低 8 位字的外设。因此第一个字(在本例中发送的是 16 位)必须位于右侧。如变量 v1 所示。

我想要一个更具表现力的版本,因此我想添加一个 constexpr 函数,该函数将第一个参数移动到结果整数最右边的位置。同时仍然使用它作为函数的第一个参数。

我确实没有想出一个好的解决方案。当我建立一个“移位值”并在离开递归时减少它。另外,这在 constexpr 环境中不起作用,这对我来说是“不行”的。也许你们有人有建议?

我确实尝试了很多事情。但大多不工作。折叠表达式也没有真正帮助。 Cpp版本并不重要(c++2a也可以)

// send 0x05 first then 0xFF
std::uint16_t v1 = (0xFFU << 8U | 0x05U); // right align first 8bit word so it is send first
std::uint16_t v2 = lower_word_first(0x05U, 0xFFU); 

// lower_word_first

static std::size_t shift = 0;

auto lower_word_first(){
    return 0;
}

template<typename unsigned_word_type, typename... words>
auto lower_word_first(unsigned_word_type word, words... ws){
    shift += 1;
    auto val = lower_word_first(ws...); // just for debugging purposes split into val
    auto res = val | word << (shift - 1) * 8U;
    shift -= 1;
    return res;
}

最佳答案

#include <cstddef>
#include <utility>

template <std::size_t... Is, typename... Ws>
constexpr auto lower_word_first(std::index_sequence<Is...>, Ws... ws)
{
    return ((ws << Is*8) | ...);
}

template <typename... Ws>
constexpr auto lower_word_first(Ws... ws)
{
    return lower_word_first(std::index_sequence_for<Ws...>{}, ws...);
}

DEMO

在这里,std::index_sequence_for ,例如

std::index_sequence_for<A, B, C, D>

产生:

std::index_sequence<0, 1, 2, 3>

然后折叠表达式变为:

(ws_0 << 0*8) | (ws_1 << 1*8) | (ws_2 << 2*8) | (ws_3 << 3*8)

或者,将参数存储在数组中,然后以相反的方向迭代。

有一些功能,以及强制特定类型的辅助函数,这可能如下所示:

#include <cstdint>
#include <array>
#include <ranges>
#include <concepts>

template <typename T>
auto type()
{
    if constexpr (std::is_same_v<T, std::uint8_t>) return std::uint16_t{};
    if constexpr (std::is_same_v<T, std::uint16_t>) return std::uint32_t{};
    if constexpr (std::is_same_v<T, std::uint32_t>) return std::uint64_t{};
}

template <std::integral W>
constexpr auto lower_word_first(W w, std::same_as<W> auto... ws)
{
    decltype(type<W>()) val{};
    const std::array a = { w, ws... };
    for (auto v : std::ranges::reverse_view{ a }) {
        val <<= 8;
        val |= v;
    }
    return val;
}

DEMO 2

关于c++ - 用于重新排序无符号整数的 Constexpr 变量模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62211848/

相关文章:

c++ - 哪种类型的继承更可取?

c++ - 远近不一致

c++ - lambda capture 是否支持可变模板参数

c++ - 返回 C++17 可变参数模板的可变参数聚合(结构)和语法 'construction deduction guide'

c++ - 为什么他们坚持在下面的示例中使用 `extern` 说明符?

c++ - 如何将无符号字符数组转换为无符号短整数

c++ - 以某种方式可以从 HANDLE 获得 HMODULE?

c++ - 如何在 c++ 类中使用模板特化,为什么它不能编译?

c++ - enable_if 模板特化自定义特征

c++ - 当结构声明被变量隐藏时的名称解析