【问题标题】:Order of parameter pack expansion参数包展开顺序
【发布时间】:2017-06-22 05:09:22
【问题描述】:

我有两个函数可以读取二进制文件。

第一个函数从文件中读取sizeof(T) 字节:

template<typename T>
T read() { ... some IO operations ... };

第二个函数使用每个模板参数多次调用第一个函数:

template<typename... Ts>
std::tuple<Ts...> read_all() {
    return std::make_tuple(read<Ts>()...);
};

除了第一个函数调用顺序外,一切正常。对于类似的东西

uint32_t a;
uint8_t b;
std::tie(a, b) = read_all<uint32_t, uint8_t>();

第一个将被称为read&lt;uint8_t&gt;(),然后是read&lt;uint32&gt;(),它颠倒了传递模板参数的顺序并混淆了文件中的字节顺序。

当然,我可以调用 read_all 以颠倒模板参数的顺序并最终得到正确的顺序,但是有没有更明显的方法呢?

【问题讨论】:

    标签: c++ templates io variadic-templates


    【解决方案1】:

    我会保持简单一点,然后这样做:

    uint32_t a;
    uint8_t b;
    std::tie(a, b) = read<std::tuple<uint32_t, uint8_t>>();
    

    这样只有一个read(),如果你直接使用元组(或结构)字段,你甚至可以跳过tie()

    【讨论】:

      【解决方案2】:

      C++ 没有指定函数参数的计算顺序。如果函数的表达式都使用流中的数据,则可能会出现以错误顺序读取对象的行为。

      但是,带括号的初始化器列表是从左到右计算的,因此如果您尝试以下操作,您应该会得到更好的结果:

      template<typename... Ts>
      std::tuple<Ts...> read_all() {
          return std::tuple<Ts...>{read<Ts>()...};
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-09
        • 1970-01-01
        • 2018-03-04
        • 2012-08-16
        • 2015-06-06
        • 2014-09-25
        • 1970-01-01
        相关资源
        最近更新 更多