什么之间的区别__PRETTY_FUNCTION__,__FUNCTION__,__func__,和他们在哪里记录?我如何决定使用哪一个?
我正在编写一些用于解析一些文本数据文件的模板类,因此很可能绝大多数的解析错误都是由于数据文件中的错误造成的,这些错误大部分都不是由程序员编写的,因此需要关于为什么应用程序无法加载的好消息,例如:
解析example.txt时出错.[MySectiom] Key的值("notaninteger")不是有效的int
我可以计算出从传递给在类模板函数和成员瓦尔参数文件,段和键名,但我不知道如何让模板函数试图转换为类型的名称.
我当前的代码看起来像,只有普通字符串的特殊化,如下:
template<typename T> T GetValue(const std::wstring §ion, const std::wstring &key)
{
std::map<std::wstring, std::wstring>::iterator it = map[section].find(key);
if(it == map[section].end())
throw ItemDoesNotExist(file, section, key)
else
{
try{return boost::lexical_cast<T>(it->second);}
//needs to get the name from T somehow
catch(...)throw ParseError(file, section, key, it->second, TypeName(T));
}
}
Run Code Online (Sandbox Code Playgroud)
Id而不是必须为数据文件可能使用的每种类型进行特定的重载,因为它们有很多...
此外,我需要一个不会产生任何运行时开销的解决方案,除非发生异常,即完全编译时解决方案是我想要的,因为这个代码被称为吨次并且加载时间已经变得有点长.
编辑:好的,这是我提出的解决方案:
我有一个类型h包含以下内容
#pragma once
template<typename T> const wchar_t *GetTypeName();
#define DEFINE_TYPE_NAME(type, name) \
template<>const wchar_t *GetTypeName<type>(){return name;}
Run Code Online (Sandbox Code Playgroud)
然后我可以在我需要处理的每种类型的cpp文件中使用DEFINE_TYPE_NAME宏(例如,在定义要开始的类型的cpp文件中).
然后链接器能够找到适当的模板特化,只要它在某处定义,否则抛出链接器错误,以便我可以添加类型.
当我在 Visual\xc2\xa0Studio\xc2\xa02019 的 C++ 控制台应用程序中使用以下最少代码时,我收到两个完全相反的警告。
\nint main()\n{\n unsigned char op1 = 0x1;\n unsigned char op2 = 0x3;\n unsigned char result1 = op1 | op2;\n unsigned char result2 = op1 || op2;\n}\nRun Code Online (Sandbox Code Playgroud)\n警告unsigned char result1 = op1 | op2;是
\n\nlnt-逻辑按位不匹配 当可能需要逻辑“||”时使用按位“|”。
\n
警告unsigned char result2 = op1 || op2;是
\n\nlnt-逻辑按位不匹配 当可能需要按位“||”时使用逻辑“||”。
\n
这有点好奇。
\n我的目的是使用按位运算符。我如何更改该行unsigned char result1 = op1 | op2;,以便 Visual\xc2\xa0Studio\xc2\xa02019 警告消失?
该警告不是来自编译器;而是来自编译器。输出没有错误。\n可能它来自ReSharper C++ …
我正在尝试包装Windows API函数以在我选择时检查错误.正如我在之前的SO问题中发现的那样,我可以使用模板函数来调用API函数,然后调用GetLastError()以检索它可能设置的任何错误.然后,我可以将此错误传递给我的Error班级让我知道.
这是模板函数的代码:
template<typename TRet, typename... TArgs>
TRet Wrap(TRet(WINAPI *api)(TArgs...), TArgs... args)
{
TRet ret = api(args...);
//check for errors
return ret;
}
Run Code Online (Sandbox Code Playgroud)
使用这个我可以有如下代码
int WINAPI someFunc (int param1, BOOL param2); //body not accessible
int main()
{
int ret = someFunc (5, true); //works normally
int ret2 = Wrap (someFunc, 5, true); //same as above, but I'll get a message if there's an error
}
Run Code Online (Sandbox Code Playgroud)
这非常有效.但是,有一个可能的问题.采取这个功能
void WINAPI someFunc();
Run Code Online (Sandbox Code Playgroud)
将其转换为模板函数时,它看起来如下:
void Wrap(void(WINAPI *api)())
{
void ret …Run Code Online (Sandbox Code Playgroud) 提供static_assert模板通常很有帮助.在模板不应该以某种方式实例化的情况下,我经常这样做
template<typename T, typename = void>
struct S
{
static_assert(false, "Unconditional error");
static_assert(sizeof(T) != sizeof(T), "Error on instantiation");
};
template<typename T>
struct S<T, std::enable_if_t<std::is_integral_v<T>>>
{
// ...
};
Run Code Online (Sandbox Code Playgroud)
static_assert即使没有实例化,第一个将立即失败S,而如果没有实例化将导致主模板,第二个将成功.
第二个static_assert显然是一个重言式,但它"取决于" T,以达到预期的效果.但这有保证吗?是否允许编译器评估这些重言式?
在这个问题中:
我们有一些关于如何让典型的 C++ 编译器在编译时打印类型名称的建议。但是,它们依赖于触发编译错误。
我的问题:我可以让 C++ 编译器在不停止编译的情况下打印类型的名称吗?
一般来说,答案是“可能不是”,因为一个有效的程序可以编译成它的目标对象,而无需在任何地方打印任何内容,所以我特别询问 GCC 和 clang,可能使用预处理器指令、编译器内置程序或任何编译器- 特定的技巧。
笔记:
using/typedef语句、模板参数值、可变参数模板等后面打印类型。如果类型明确可用,您可以使用类似的东西#message "my type is unsigned long long"(如@NutCracker 建议的那样)。但这不是问题的内容。c++ ×6
compile-time ×3
c ×1
c++11 ×1
clang++ ×1
debug-print ×1
g++ ×1
standards ×1
templates ×1
typechecking ×1
typename ×1