[英]Replacing a functor by a templated function
我目前正在刷新我的旧C ++项目,试图利用现代C ++带来的所有好处。 该项目的某些部分是关于访问uint8_t数组,返回uint8_t,uint16_t或uint32_t,具体取决于所需的数据。 为了简化问题,我将不考虑任何与字节序有关的问题。
我完成了以下课程,使用函子访问数据:
template<std::size_t sz>
class Read
{
public:
template <std::size_t sz>
struct Read_traits { };
template <>
struct Read_traits<8> { using internal_type = std::uint8_t; };
template <>
struct Read_traits<16> { using internal_type = std::uint16_t; };
template <>
struct Read_traits<32> { using internal_type = std::uint32_t; };
template <>
struct Read_traits<64> { using internal_type = std::uint64_t; };
using read_type = typename Read_traits<sz>::internal_type;
template<typename T, ::std::size_t N>
read_type operator()(const ::std::array<T, N> & arr, const ::std::uint32_t& adr) const {
read_type returnValue{};
for (uint8_t i = 0; i <= sizeof(read_type) - 1; ++i) {
returnValue <<= 8;
returnValue |= arr[adr + i];
}
return returnValue;
};
};
用法是
int main()
{
std::array <uint8_t, 0x4> memory {0xFE, 0xDC, 0xBA, 0x98};
Read<32> r32;
auto val32 = r32(memory, 0);
std::cout << "32 bits: 0x" << std::hex << val32 << std::endl;
return 0;
}
它以我想要的方式工作,但是我想知道是否有可能仍然使用traits来代替functor创建一个常规函数?
IE取代2行函子调用:
Read<32> r; auto val = r(memory, 0);
通过单行功能:
auto val Read<32>(memory, 0);
我尝试了一些不确定的事情,而且由于我还不是模板专家,所以我可能正在追逐甚至无法实现的事情...
感谢您阅读我:)
您可以这样做:
// Maps 8, 16 and 32 to uint8_t, uint16_t and uint32_t, respectively
template<size_t Size>
using SizedUInt = std::conditional_t<Size == 8, uint8_t,
std::conditional_t<Size == 16, uint16_t,
std::conditional_t<Size == 32, uint32_t, void>>>;
template<size_t Size, typename T, size_t N>
SizedUInt<Size> read(const std::array<T, N>& arr, uint32_t adr)
{
SizedUInt<Size> returnValue{};
for (uint8_t i = 0; i <= sizeof(SizedUInt<Size>) - 1; ++i) {
returnValue <<= 8;
returnValue |= arr[adr + i];
}
return returnValue;
}
SizedUInt
是模板别名,它使用嵌套的conditional_t
模板选择正确的类型。 当模板使用的值不同于8、16或32时,我将最深的conditional_t
的“ false”类型设置为void
以触发编译错误。
或者,您可以使用模板类执行此操作:
// create a temporary of type Read<32> and call its call operator
auto val = Read<32>{}(memory, 0);
将Read
作为类的唯一原因似乎是Read_traits
的定义。 但是您也可以在前者之外定义后者。 由于C ++的丑陋,仅需要一些其他的typename
关键字...
请注意,首先提供sz
template参数。 调用时,它是显式使用的唯一参数。 其余部分与以前相同。
#include <cstdint>
#include <iostream>
#include <array>
template <std::size_t sz>
struct ReadType { };
template <>
struct ReadType <8> { using type = std::uint8_t; };
template <>
struct ReadType <16> { using type = std::uint16_t; };
template <>
struct ReadType <32> { using type = std::uint32_t; };
template <>
struct ReadType <64> { using type = std::uint64_t; };
template <std::size_t sz, typename T, ::std::size_t N>
typename ReadType<sz>::type read(const ::std::array<T, N> & arr, const ::std::uint32_t& adr) {
using read_type = typename ReadType<sz>::type;
read_type returnValue{};
for (uint8_t i = 0; i <= sizeof(read_type) - 1; ++i) {
returnValue <<= 8;
returnValue |= arr[adr + i];
}
return returnValue;
};
int main()
{
std::array <uint8_t, 0x4> memory {0xFE, 0xDC, 0xBA, 0x98};
auto val32 = read<32>(memory, 0);
std::cout << "32 bits: 0x" << std::hex << val32 << std::endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.