推论具有默认参数的variadic模板参数
我正在尝试创建一个基本的记录仪。这是一个小例子。
template<typename ...str>
struct log {
log(
str &&...args,
const char *file = __builtin_FILE(),
const char *func = __builtin_FUNCTION(),
const size_t line = __builtin_LINE()
) {
std::cout << "[" << file << "] [" << func << "] [" << line << "] ";
((std::cout << args << " "), ...);
std::cout << std::endl;
}
};
template<typename ...str>
log(str &&...args) -> log<str ...>;
我希望能够接收呼叫者信息以及可变数量的参数。在上面的示例中,我可以创建一个这样的实例。
log inst("THIS WORKS", "ASD", "ASD");
>>> [.../main.cpp] [main] [10] THIS WORKS ASD ASD
我还希望能够指定记录级别。这是麻烦开始的地方。假设我有以下记录级别的枚举,我想让它成为记录器的模板参数。以下是我认为这会起作用的方式。
enum logging_level {
INFO,
};
template<logging_level level, typename ...str>
struct log {
...
};
template<logging_level level, typename ...str>
log(str &&...args) -> log<level, str ...>;
log<INFO> inst("THIS DOESN'T WORK", "ASD", "ASD");
我在这里得到的错误是,参数传递到默认参数中,而不是variadic参数中。
>>> error: invalid conversion from ‘const char*’ to ‘size_t’ {aka ‘long unsigned int’} [-fpermissive]
>>> 33 | log<INFO> inst("THIS DOESN'T WORK", "ASD", "ASD");
>>> | ^~~~~
>>> | |
>>> | const char*
这远远超过了我的C ++模板知识。一个简单的解决方案是抛弃variadic模板,然后通过一个字符串,但我想看看这是否可以工作。有人知道如何进行编译吗?
谢谢。
I am trying to create a basic logger. Here is a small example.
template<typename ...str>
struct log {
log(
str &&...args,
const char *file = __builtin_FILE(),
const char *func = __builtin_FUNCTION(),
const size_t line = __builtin_LINE()
) {
std::cout << "[" << file << "] [" << func << "] [" << line << "] ";
((std::cout << args << " "), ...);
std::cout << std::endl;
}
};
template<typename ...str>
log(str &&...args) -> log<str ...>;
I want the ability to receive caller information along with a variable number of arguments. With the above example, I can create an instance like this.
log inst("THIS WORKS", "ASD", "ASD");
>>> [.../main.cpp] [main] [10] THIS WORKS ASD ASD
I also want the ability to specify logging levels. This is where the trouble begins. Say I have an enum with the following logging levels, and I want to make it a template argument for the logger. The following is how I thought this would work.
enum logging_level {
INFO,
};
template<logging_level level, typename ...str>
struct log {
...
};
template<logging_level level, typename ...str>
log(str &&...args) -> log<level, str ...>;
log<INFO> inst("THIS DOESN'T WORK", "ASD", "ASD");
The error I get here is that the arguments are passed into the default arguments, not the variadic arguments.
>>> error: invalid conversion from ‘const char*’ to ‘size_t’ {aka ‘long unsigned int’} [-fpermissive]
>>> 33 | log<INFO> inst("THIS DOESN'T WORK", "ASD", "ASD");
>>> | ^~~~~
>>> | |
>>> | const char*
This is getting well above my C++ template knowledge. An easy solution is to ditch the variadic template and just pass in a string but I wanted to see if this could work. Does anyone know how to make this compile?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不能在某些论点上使用CTAD,而不能在其他论点上使用。尽管使用标签调度,您可以使类似的语法工作。您需要将日志级别的规范移至参数列表,以实现这一目标。
请注意,在下面的示例中,我正在使用
std :: source_location
(C ++ 20)独立编译器:You cannot use CTAD on some arguments, but not on the others. You could make a similar syntax work though using tag dispatch. You need to move the specification of the log level to the argument list to accomplish this.
Note that in the following example I'm using
std::source_location
(C++20) to be compiler independent: