- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 Windows 上的 Visual Studio 编写了一个简单的日志记录类,它支持 C++ 中的可变参数模板。我创建了一个通用的 Log
具有许多专门化的功能模板,以满足可能输入的常见组合。
#pragma once
#include <Windows.h>
#include <locale>
#include <codecvt>
#include <string>
#include <sstream>
#include <utility>
using namespace std;
inline static string to_utf8(const wstring& s) {
wstring_convert<codecvt_utf8_utf16<wchar_t>> utf16conv;
return utf16conv.to_bytes(s);
}
class Logger {
public:
HANDLE file_handle;
wchar_t file_path[MAX_PATH + 1];
inline Logger(HANDLE handle) : file_handle(handle), file_path{} {
}
inline Logger(const string& path) : Logger(path.c_str()) {
}
inline Logger(const wstring& path) : Logger(path.c_str()) {
}
inline Logger(const char* path) : file_handle(NULL) {
wstring_convert<codecvt_utf8_utf16<wchar_t>> converter;
wcscpy_s(file_path, MAX_PATH + 1, converter.from_bytes(path).c_str());
}
inline Logger(const wchar_t* path) : file_handle(NULL) {
wcscpy_s(file_path, MAX_PATH + 1, path);
}
private:
inline void VerifyInitialize() {
if ((file_handle == NULL || file_handle == INVALID_HANDLE_VALUE) && file_path[0] != '\0') {
file_handle = CreateFileW(file_path, FILE_GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(file_path, 0, NULL, FILE_END);
}
}
public:
inline void Log() {
}
template<typename ...Rest>
inline void Log(const char* first, Rest... params) {
VerifyInitialize();
if (file_handle == NULL || file_handle == INVALID_HANDLE_VALUE)
return;
DWORD written;
WriteFile(file_handle, first, static_cast<DWORD>(strlen(first)), &written, NULL);
Log(params...);
}
template<typename ...Rest>
inline void Log(const char first, Rest... params) {
char str[2];
str[0] = first;
str[1] = '\0';
Log(str, params...);
}
template<typename ...Rest>
inline void Log(const string* first, Rest... params) {
VerifyInitialize();
if (file_handle == NULL || file_handle == INVALID_HANDLE_VALUE)
return;
DWORD written;
WriteFile(file_handle, first->c_str(), static_cast<DWORD>(first->size()), &written, NULL);
Log(params...);
}
template<typename ...Rest>
inline void Log(const string& first, Rest... params) {
Log(&first, params...);
}
template<typename ...Rest>
inline void Log(const wstring* first, Rest... params) {
Log(*first, params...);
}
template<typename ...Rest>
inline void Log(const wstring& first, Rest... params) {
Log(to_utf8(first), params...);
}
template<typename ...Rest>
inline void Log(const wchar_t* first, Rest... params) {
Log(wstring(first), params...);
}
template<typename ...Rest>
inline void Log(const wchar_t first, Rest... params) {
wchar_t str[2];
str[0] = first;
str[1] = '\0';
Log(str, params...);
}
template<typename First, typename ...Rest>
inline void Log(First first, Rest... params) {
printf("%s\n", typeid(First).name());
if (is_const<First>::value) {
stringstream stream;
stream << first;
Log(stream.str(), params...);
} else
Log(const_cast<const First>(first), params...);
}
inline ~Logger() {
if (!(file_handle == NULL || file_handle == INVALID_HANDLE_VALUE)) {
CloseHandle(file_handle);
file_handle = NULL;
}
}
};
该代码适用于 const 值。但是,如果我像这样引入非常量参数:
int main() {
Logger logger(("output.txt"));
wchar_t sometext[3];
sometext[0] = '1';
sometext[1] = '8';
sometext[2] = '\0';
logger.Log(sometext, L"\n");
return 0;
}
特化没有被调用,而是最后一个通用的 void Log(First first, Rest... params)
被称为,它使用 stringstream
并将指针写为字符串而不是字符串本身。
如果我删除 const
来自所有重载参数,当我调用 main()
它有效,但如果我更换 sometext
用const char*
, 然后是最后一个泛型 void Log(First first, Rest... params)
被调用而不是特化(即删除 const
不能解决问题)。
因此,为了尝试两全其美,我尝试添加以下条件:
template<typename First, typename ...Rest>
inline void Log(First first, Rest... params) {
if (is_const<First>::value) {
stringstream stream;
stream << first;
Log(stream.str(), params...);
} else
Log(const_cast<const First>(first), params...);
}
其基本原理是指示编译器“首先搜索 const 特化重载,如果未找到,则回退到使用 stringstream
”。
但是,我遇到了堆栈溢出。为了调试,我添加了 printf("%s\n", typeid(First).name());
就在 if
之前条件,输出为:
wchar_t * __ptr64
wchar_t * __ptr64
wchar_t * __ptr64
wchar_t * __ptr64
....
显然,const_cast<const First>(first)
实际上似乎并没有转换到const
, 即使 is_const::value
确实在返回 false
.我也尝试过使用 std::as_const
, 但结果没有差异。
为什么转换不起作用?请问我该如何解决?
最佳答案
如果 First
是 wchar_t*
转换将创建一个 wchar_t* const
,而不是 const wchar_t*
.强制转换不是类型名称的文本替换。
因此您创建了一个不匹配任何特化的新类型,并获得对通用 Log
函数的递归调用。
关于c++ - const_cast 似乎被 C++ 模板忽略了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46575369/
我正在阅读 C++ Primer,我发现了一些非常奇怪且难以理解的东西: Record lookup(Account&); //Record and Account are two unrelate
我的问题是,为什么代码的第一部分不起作用而第二部分有效。非常量指针应该修改之前使用 const_cast 的 const 值,但是对于整数这个技巧不起作用。您能解释一下为什么会这样吗? const i
我已经阅读了很多关于 C++ 中的 const_cast 被认为是错误和危险的讨论,除了向后兼容 C 代码之外,不应将其用于任何其他用途。我大体上同意。 但是最近我遇到了以下用例,这让我感到好奇。 我
C++ Primer 一书的第 6.4 章陈述如下: In § 4.11.3 (p. 163) we noted that const_casts are more useful in the con
我看到这个 post这解释了const_cast<>并说使用指针/引用是有益的。但是,请考虑以下代码: 1- const_cast(xadj) 我得到 invalid const_cast from
我正在阅读有关 c++ 中的 const_cast 运算符 1.我无法理解的第一件奇怪的事情是 const_cast 运算符语法即 -const_cast----(--expression--)---
这个问题在这里已经有了答案: const_cast doesn't work c++? [duplicate] (3 个答案) 关闭 6 年前。 在const_cast之后,main函数中的值没有变
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 我有以下代码: int main(){
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 #include using nam
我想使用 C++ 格式进行此转换,它以 C 方式工作。但是当我尝试使用 C++ 格式时它失败了。 有效! void req_password(const void *data, size_t data
我有一个管理输入的类。要显示和更改键绑定(bind),重要的是在完成后将其提交给管理器之前,为调用者提供它可以拥有和更改的绑定(bind)的映射。但是,这个映射中可以插入/删除什么的具体规则只有管理者
我对 const_cast 的返回类型有点困惑?尖括号内的类型是否 <>是返回类型吗? const int i = 5; int b = const_cast(i); 是const_cast返回 in
我有一个函数 static bool Validate(const char& letter, string& aWord) 我需要调用它 Validate(letter, aWord); // wh
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 考虑以下代码: 我声明了一个新的引用端
我有一个大型库,它实现了一些不可变的数据结构。可以想象,其中几乎所有内容都是 const合格的。有一些选择部分不是 const,例如引用计数器。为了处理嵌入结构中的引用计数器,这些引用计数器只能通过
长话短说是否适用于: mapm; m.insert( make_pair( 1, 40 ) ); for( map::iterator it = m.begin(); it !
据我所知,在类中创建常量函数对于读/写编译器优化很有用。 类中的常量函数意味着类成员在函数执行期间将保持不变。但是,您可以通过 const 强制转换隐式参数来绕过此问题(当然,这是一种非常糟糕的做法)
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 考虑以下代码: 我声明了一个新的引用端
考虑以下 C++03 程序: #include struct T { mutable int x; T() : x(0) {} }; void bar(int& x) { x
我正在查看我即将开始使用的 API 的一些示例代码。以下模式让我有点困惑: char* str; str = const_cast("Hello World"); printf("%s ", str)
我是一名优秀的程序员,十分优秀!