利用cmake和模板编程进行字节序转换

前言

想利用模板编程进行编译期计算,想先判断主机字节序然后利用std::enable_if(C++17使用if constexpr)根据字节序是大端还是小端来判断是否进行字节序转换。但第一步编译期判断字节序不成功,因为union类型不能constexpr, 起对成员的选择访问是运行时的;而又不想运行时判断,所以要用其它方法代替。首先gcc编译器是有定义宏,考虑到平台扩展性还是选用了cmake的功能。
另外我做的是本机字节序往网络字节序的互转,因此只有判断是否是大端字节序,如果本机是大端则直接return,本机是小端则转换。

cmake字节序判断

cmake提供了判断字节序的功能,在cmake 3.20之前是TestBigEndian,之后由CMAKE_BYTE_ORDER替代,官方文档:
TestBigEndian
Deprecated since version 3.20: Supserseded by the CMAKE
_BYTE_ORDER variable.
Check if the target architecture is big endian or little endian.
test_big_endian
test_big_endian()
Stores in variable either 1 or 0 indicating whether the target architecture is big or little endian.
用法如下:

    if (CMAKE_CXX_BYTE_ORDER STREQUAL "BIG_ENDIAN")
        set(IS_BIG_ENDIAN_TARGET 1)
    else()
        set(IS_BIG_ENDIAN_TARGET 0)
    endif()
else()
    include(TestBigEndian)
    test_big_endian(BIG_ENDIAN)
    set(IS_BIG_ENDIAN_TARGET ${BIG_ENDIAN})
endif()

然后利用configure_file把IS_BIG_ENDIAN_TARGET传入代码中,或用add_definition(-DIS_BIG_ENDIAN_TARGET=1(or 0))

configure_file(${PROJECT_SOURCE_DIR}/include/common/config.h.in
    ${PROJECT_BINARY_DIR}/include/common/config.h)

# 注意后面要target_include_directories里指定这个路径
// config.h.in
#ifndef CONFIG_H
#define CONFIG_H

#ifndef IS_BIG_ENDIAN_TARGET
#define IS_BIG_ENDIAN_TARGET @DIS_BIG_ENDIAN_TARGET@
#endif

#endif

模板编程进行字节序转换

    template <class T>
    static std::enable_if_t<!IS_BIG_ENDIAN_TARGET && (sizeof(T) > 1), void>
    AdjustEndianness(T& value) {
        uint8_t* value_begin = reinterpret_cast<uint8_t*>(&value);
        std::reverse(value_begin, value_begin + sizeof(T));
    }

    template <class T>
    static std::enable_if_t<IS_BIG_ENDIAN_TARGET || (sizeof(T) == 1), void>
    AdjustEndianness(T& value) {
        return;
    }

    template <class T>
    static void AdjustVarsEndianness(T&& value) {
        AdjustEndianness(std::forward<T>(value));
    }

    template <class T, class ...ArgTypes>
    static void AdjustVarsEndianness(T&& value, ArgTypes&&... args) {
        AdjustEndianness(std::forward<T>(value));
        AdjustVarsEndianness(std::forward<ArgTypes>(args) ...);
    }

这里只有在本机字节序和网络字节序不一致且T的size大于1时才转换字节序,因为我这个场景时通过网络发送信息,保证client和server端解析不会出错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值