繁体   English   中英

通过模板函数替换函子

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM