我可以有 const 参数包吗?
Can I have const parameter packs?
好吧
为了好玩而开发一个简单的日志系统,遇到了一个有趣的问题。我认为能够按照以下方式写一些东西会很好:
Log(Info, "Result: {}", value);
给我这样的结果
Result: 45
(这里使用fmt的格式样式。)
所以我这样设置函数:
template <typename ...args_t>
void Log(LogLevel Level, const char* Message, args_t&&... Args)
效果很好,没问题。但是,我的想法是,如果参数未被函数修改,则应将其标记为 const(用于优化和给程序员的注释),所以我尝试了这个:
template <typename ...args_t>
void Log(const LogLevel Level, const char* Message, const args_t&&... Args)
这一直给我错误,VS2017 给了我
error C2665: 'Log': none of the 4 overloads could convert all the argument types
我是不是做错了?我不应该担心参数包的常量性吗?有一个更好的方法吗?这个参数打包业务有时让我难以理解。
(我花了大约 3 个小时来研究这个问题,但找不到任何关于堆栈溢出或整个互联网的相关信息,如果这个问题已经在其他地方得到解答,请原谅我。)
您使用的是转发引用,而您真正想要的是常量引用。
将 args_t&&
替换为 const args_t&
。
转发引用使用与右值引用相同的语法声明,带有双 &
(所以 &&
)。一个与另一个的区别在于它是否出现在 推导上下文 中:转发引用被推导,右值引用不是。换句话说,如果编译器使用您的函数参数来确定模板参数是什么(例如您的情况),那么它就是转发引用。否则,它是一个右值引用。
在您的情况下,const
引用更可取,因为您明确打算不修改参数。由于您永远不想通过非 const
引用接受参数,因此您不需要完美的转发,使用 const
引用将使您获得编译器检查的不变性以及接受 prvalues 的能力(例如文字等)。
好吧
为了好玩而开发一个简单的日志系统,遇到了一个有趣的问题。我认为能够按照以下方式写一些东西会很好:
Log(Info, "Result: {}", value);
给我这样的结果
Result: 45
(这里使用fmt的格式样式。)
所以我这样设置函数:
template <typename ...args_t>
void Log(LogLevel Level, const char* Message, args_t&&... Args)
效果很好,没问题。但是,我的想法是,如果参数未被函数修改,则应将其标记为 const(用于优化和给程序员的注释),所以我尝试了这个:
template <typename ...args_t>
void Log(const LogLevel Level, const char* Message, const args_t&&... Args)
这一直给我错误,VS2017 给了我
error C2665: 'Log': none of the 4 overloads could convert all the argument types
我是不是做错了?我不应该担心参数包的常量性吗?有一个更好的方法吗?这个参数打包业务有时让我难以理解。
(我花了大约 3 个小时来研究这个问题,但找不到任何关于堆栈溢出或整个互联网的相关信息,如果这个问题已经在其他地方得到解答,请原谅我。)
您使用的是转发引用,而您真正想要的是常量引用。
将 args_t&&
替换为 const args_t&
。
转发引用使用与右值引用相同的语法声明,带有双 &
(所以 &&
)。一个与另一个的区别在于它是否出现在 推导上下文 中:转发引用被推导,右值引用不是。换句话说,如果编译器使用您的函数参数来确定模板参数是什么(例如您的情况),那么它就是转发引用。否则,它是一个右值引用。
在您的情况下,const
引用更可取,因为您明确打算不修改参数。由于您永远不想通过非 const
引用接受参数,因此您不需要完美的转发,使用 const
引用将使您获得编译器检查的不变性以及接受 prvalues 的能力(例如文字等)。