参数包扩展顺序

时间:2017-02-05 01:57:04

标签: c++ templates io variadic-templates

我有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并最终得到正确的顺序,但是有更明显的方法吗?

2 个答案:

答案 0 :(得分:11)

C ++没有指定评估函数参数的顺序。如果函数的表达式都使用了流中的数据,则可以获得以错误顺序读取对象的行为。

支持初始化列表从左到右进行评估,但是如果你尝试这样的话,你应该会得到更好的结果:

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

答案 1 :(得分:2)

我会更简单一点,并且这样做:

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

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