我可以有 const 参数包吗?

Nem*_*emo 2 c++ constants variadic-templates c++17

好吧所以

为了好玩而开发一个简单的日志系统,遇到了一个有趣的问题。我认为能够写一些类似以下内容的东西会很好:

Log(Info, "Result: {}", value);

给我一个像这样的结果

Result: 45

(此处使用 fmt 的格式样式。)

所以我这样设置函数:

template <typename ...args_t>
void Log(LogLevel Level, const char* Message, args_t&&... Args)
Run Code Online (Sandbox Code Playgroud)

效果很好,没有任何问题。但是,我的想法是,如果函数未修改参数,则应将其标记为 const (用于优化并作为给程序员的注释),所以我尝试了以下方法:

template <typename ...args_t>
void Log(const LogLevel Level, const char* Message, const args_t&&... Args)
Run Code Online (Sandbox Code Playgroud)

这一直给我错误,VS2017给了我

error C2665: 'Log': none of the 4 overloads could convert all the argument types

我只是做错了吗?我不应该担心参数包常量吗?有一个更好的方法吗?有时,这个参数打包业务很难让我理解。

(我花了大约 3 个小时研究这个问题,但在堆栈溢出或整个互联网上找不到任何相关信息,如果这个问题已经在其他地方得到了回答,请原谅我。)

Sum*_*ood 6

当您真正想要的是 const 引用时,您正在使用转发引用。

args_t&&用。。。来代替const args_t&

转发引用使用与右值引用相同的语法声明,并带有双精度值&(so &&)。两者的区别在于它是否出现在推导的上下文中:转发引用是推导的,而右值引用则不是。换句话说,如果编译器使用您的函数参数来确定模板参数是什么(例如您的情况),那么它就是转发引用。否则,它是一个右值引用。

在您的情况下,const最好使用引用,因为您明确不打算修改参数。由于您永远不想通过非const引用接受参数,因此不需要完美的转发,使用引用const将为您提供编译器检查的不变性以及接受纯右值(例如文字等)的能力。