首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用默认参数推断可变模板参数

用默认参数推断可变模板参数
EN

Stack Overflow用户
提问于 2022-06-05 17:17:27
回答 1查看 70关注 0票数 2

我正在尝试创建一个基本的记录器。下面是一个小例子。

代码语言:javascript
复制
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 ...>;

我希望能够接收调用者的信息以及可变数量的参数。使用上面的示例,我可以创建这样一个实例。

代码语言:javascript
复制
log inst("THIS WORKS", "ASD", "ASD");

>>> [.../main.cpp] [main] [10] THIS WORKS ASD ASD

我还希望能够指定日志记录级别。这就是麻烦开始的地方。假设我有下面的日志记录级别,我想让它成为记录器的模板参数。以下是我认为这是如何运作的。

代码语言:javascript
复制
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");

这里我遇到的错误是,参数被传递到默认参数中,而不是变量参数。

代码语言:javascript
复制
>>> 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++模板知识。一个简单的解决方案是抛弃变量模板,只传递一个字符串,但我想看看这是否有效。有人知道如何编译吗?

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-05 18:04:08

不能在某些参数上使用CTAD,而不能在其他参数上使用CTAD。通过使用标记分派,您可以使用类似的语法。为此,您需要将日志级别的规范移到参数列表中。

注意,在下面的示例中,我使用std::source_location (C++20)独立于编译器:

代码语言:javascript
复制
enum class LogLevel
{
    INFO
};

template<LogLevel logLevel>
struct LogLevelInfoTag {
    constexpr operator LogLevel()
    {
        return logLevel;
    }
};

constinit LogLevelInfoTag<LogLevel::INFO> INFO;

template<LogLevel logLevel, typename ...str>
struct log {
    log(
        LogLevelInfoTag<logLevel>,
        str &&...args,
        std::source_location location = std::source_location::current()
    ) {

        std::cout << "[" << location.file_name() << "] [" << location.function_name() << "] [" << location.line() << "] ";
        ((std::cout << args << " "), ...);
        std::cout << std::endl;
    }
};

template<LogLevel logLevel, typename ...str>
log(LogLevelInfoTag<logLevel>, str &&...args) -> log<logLevel, str ...>;

// log<INFO> inst("THIS DOESN'T WORK", "ASD", "ASD"); // (desired syntax)
log inst(INFO, "THIS DOESN'T WORK", "ASD", "ASD");
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72509526

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档