参数包扩展顺序

Order of parameter pack expansion

本文关键字:顺序 扩展 包扩展 参数      更新时间:2023-10-16

我有 2 个函数来读取二进制文件。

第一个函数从文件中读取 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<uint8_t>(),之后read<uint32>()它颠倒了传递模板参数的顺序并弄乱了文件中字节的顺序。

当然,我可以用模板参数的相反顺序调用read_all并最终获得正确的顺序,但是有没有更明显的方法可以做到这一点?

C++不

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

但是,大括号初始值设定项列表是从左到右计算的,因此,如果您尝试以下操作,应该会获得更好的结果:

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

我会让它更简单一点并这样做:

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

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