我可以有 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 的能力(例如文字等)。