c++ - 混合使用可变参数的默认值 arg
问题描述
问题代码:
#include <filesystem>
#include <iosfwd>
#include <string>
#include <format>
#include <source_location>
#include <iostream>
#include <array>
#include <wchar.h>
#include <fstream>
#include <memory>
#include <exception>
using std::filesystem::path;
using std::array;
using std::source_location;
using std::format;
using std::vformat;
using std::wstring;
class CStreamToTextFileU {
std::unique_ptr<std::wofstream> m_pFileStr;
CStreamToTextFileU() = delete;
public:
explicit CStreamToTextFileU(const std::filesystem::path& Filepath, std::ios::openmode nMode) :
m_pFileStr(std::make_unique<std::wofstream>(Filepath, nMode | std::ios::out)) {
if((m_pFileStr.get() == nullptr) || (! m_pFileStr->is_open()))
throw std::ios::failure("Unable to open file for writing");
}
CStreamToTextFileU(CStreamToTextFileU&& Other) noexcept : m_pFileStr(std::move(Other.m_pFileStr)) {}
CStreamToTextFileU &operator=(CStreamToTextFileU&& Other) & noexcept {
if(this != &Other)
m_pFileStr = std::move(Other.m_pFileStr);
return(*this);
}
~CStreamToTextFileU() noexcept {
if(m_pFileStr != nullptr)
m_pFileStr->close();
}
std::wofstream& operator()() const { return(*(m_pFileStr.get())); }
};
class RLog {
CStreamToTextFileU LogStream;
public:
RLog() = delete;
explicit RLog(const path Filepath);
template<auto Separator = L' ', typename... Args>
void LogMsg(Args&&... args, const std::source_location Cur = std::source_location::current());
}; // class RLog()
// template<typename... Args> LogMsg(Args&&...) -> LogMsg<Args...>;
RLog::RLog(const path Filepath) : LogStream(CStreamToTextFileU(Filepath, std::ios::trunc)) {
LogStream() << L"Log file: " << Filepath << L"\n\n";
} // RLog::RLog()
template<auto Separator, typename... Args>
void RLog::LogMsg(Args&&... args, const std::source_location Cur) {
static int n{};
RLog::LogStream() << format(L"{:04} File: {}({}:{}) `{}`:",
n++, Cur.file_name(), Cur.line(),
Cur.column(), Cur.function_name());
(... , [] (const auto&& arg) -> const auto { RLog::LogStream() << Separator
<< std::forward<Args>(arg); } (args));
RLog::LogStream() << L'\n';
} // RLog::LogMsg()
int main() {
path LogPath {L"RLogFile.txt"};
RLog Lg {LogPath};
Lg.LogMsg(L"This is an", L"error", L'\n');
} // main()
我正在用最新的 VS 编译。引用的代码将使用最新的 x86 VS 编译器和标志 /std:c++latest 在编译器资源管理器中运行。我得到的错误是:
example.cpp
<source>(70): error C2672: 'RLog::LogMsg': no matching overloaded function found
<source>(70): error C2780: 'void RLog::LogMsg(Args &&...,const std::source_location)': expects 2 arguments - 3 provided
<source>(48): note: see declaration of 'RLog::LogMsg'
Compiler returned: 2
我尝试了多种方法来解决这个问题,包括不同的参数顺序、将 LogMsg() 嵌入嵌套结构中、使 source_location 参数成为模板参数(不能从默认值推断)等等。注释掉的推导指南可以修复它,但它不起作用,因为问题函数是成员,而不是构造函数,所以编译器只是将其视为损坏的函数声明。
代码的想法应该很明显:在包含您要记录的所有位置的范围内调用类构造函数,然后调用 LogMsg() 函数来创建日志消息。我宁愿不离开这个计划。我知道我可以通过打开和关闭每条消息的文件流来解决问题,因为那样整个事情都可能在类构造函数中,但这似乎不优雅,我宁愿让它工作。
解决方案
推荐阅读
- javascript - 如何将 body.addClass("className") 从父文档应用到 iframe
- kubernetes-helm - 连接来自 configMap 和 secret 的值
- amazon-web-services - 将 aws iam 用户限制到特定区域 (eu-west-1)
- javascript - 输入掩码允许字母数字文本
- javascript - 通过 props 传递的更新数组
- c# - 如何获取超链接文本
- spring - 在查询字符串中传递的 url 的 spring 云网关身份验证
- angular - 如何对带有收藏夹的材料表进行排序?
- shell - Shell 命令 grep 来自包含 .GZ 文件的 .TAR 文件的记录
- sql - SQL 中的差距分析(财务)