转发(forward) 出错的情况
1. forward 不支持初始化列表, 或者说, forward 无法推导多个参数的集合.
2. 一些编译器对于 static const val 的态度是直接替换, 如 static const val = 7; 那么, 对于函数 Func(val) 就等于 Func(7). 可是如果未定义的 static const val 传入模板并被 forward, 那么就可能会导致不可预知的错误.
3. 当尝试 forward 一个函数指针时, 如果该函数被重载, 那么就会出现错误, 因为模板无法确定传入哪个指针. 当然你如果任性, 非要传入某个已经被重载的函数指针, 那么最好传入它的别名.
4. 最后一个会导致 forward 失败的情况是, 当位域(bitfiled) 被用作函数的参数时:
struct IPv4Header{ std::uint_t version : 4 , IHL : 4 , DSCP : 6 , ECN : 2 , totalLength : 16; ... };
设此有一个
IPv4Header h;
如果你是要直接转发 h.totalLength 那么是可以的. 但是, 如果是先把它作为参数传入以 T&& 作为函数参数的模板函数时, 就是另一回事了, 因为 h.totalLength 是个非常量位域(non-const bitfiled) 而函数参数则是一个引用. 在底层, 机器看待引用和指针实际是没有分别的, 所以无法使用引用或是指针去绑定任意二进制码. 所以一个绑定位域的指针是不存在的. 好的, 那么如果我就是任性, 非要转发一个位域, 该怎么办呢? 答案其实很简单, 只要过渡一下, 问题迎刃而解:
//先接住它 auto length = static_cast<std::uint16_t>(h.totalLength);
总结:
forward 很厉害, 但不是万能的, 当模板类型推断失败, 或是推导出的类型不正确时它也会出错. 值得欣慰的是, 出错的情况是极少且可控的, 只要牢记并注意以上几种情况, 就不会跳进 forward 的坑. 就酱.