我正在使用首先发送最低 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...);
}
在这里,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)
或者,将参数存储在数组中,然后以相反的方向迭代。
有一些c++20功能,以及强制特定类型的辅助函数,这可能如下所示:
#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;
}
关于c++ - 用于重新排序无符号整数的 Constexpr 变量模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62211848/