C++ 在Qt/GCC/C++;;如何创建一个包装器,既捕获参数表达式文本,又返回/强制转换参数';什么是显式类型? 背景故事(你可以跳过)
为了尽可能地形成问题,我被告知C++ 在Qt/GCC/C++;;如何创建一个包装器,既捕获参数表达式文本,又返回/强制转换参数';什么是显式类型? 背景故事(你可以跳过),c++,qt,gcc,polymorphism,preprocessor,C++,Qt,Gcc,Polymorphism,Preprocessor,为了尽可能地形成问题,我被告知#define宏的第二组括号不像我想象的那样是返回,而是一个转换。据我所知;捕获表达式文本的唯一方法是使用#define宏。棘手的部分,也许是不可能的,是捕获显式类型的文本,但我知道什么 还有,;我将其指定给Qt而不仅仅是C++/gcc的原因是,我认为解决方案可能涉及像QVariant这样的类,它添加了一些多态性,但是这并不理想,因为很难区分一些基本类型,比如intvsbool 我希望达到的目标 基本上,我想要一个包装器,我猜是一个宏,它将记录嵌套表达式文本及其值,
#define
宏的第二组括号不像我想象的那样是返回
,而是一个转换
。据我所知;捕获表达式文本的唯一方法是使用#define
宏。棘手的部分,也许是不可能的,是捕获显式类型
的文本,但我知道什么
还有,;我将其指定给Qt而不仅仅是C++/gcc的原因是,我认为解决方案可能涉及像QVariant
这样的类,它添加了一些多态性,但是这并不理想,因为很难区分一些基本类型,比如int
vsbool
我希望达到的目标
基本上,我想要一个包装器,我猜是一个宏,它将记录嵌套表达式文本及其值,并返回其确切的嵌套类型(无隐式转换)
例如:
/* Basic Definitions */
// log() could be overloaded or use different namespaces if need be
// and have preproccessor directives choose the appropriate one,
// although I dont suspect that is possible.
QVariant log(QString expression, QVariant value, QString type);
// TYPE is placeholder code. Normally I specify a real type like "bool"
// I am hoping TYPE can represent the captured type text
// #EXPR returns the text of the expression, in case you didnt know
#define LOG(EXPR)(TYPE)(log(#EXPR, EXPR, TYPE));
在此示例代码中:
/* Sample Code */
QString path;
if (LOG(path.isEmpty())) {
path = LOG(QDir::currentPath());
}
包装器LOG
应记录以下内容:
Expression: "path.isEmpty()" Value: "True" Type: "bool"
Expression: "QDir::currentPath()" Value: "/home/akiva/Programming/" Type: "QString"
我想看看我是否可以在不必求助于多个宏名称空间的情况下实现这一点,例如:
/* Bad solution because I dont want to have to specify LOG_bool & LOG_QString */
QString path;
if (LOG_bool(path.isEmpty())) {
path = LOG_QString(QDir::currentPath());
}
我想,如果我能捕捉到这种类型的文本,一种可能的解决方案就会显现出来,但我对所有的解决方案都持开放态度,不管是宏、模板、函数还是其他什么
我的最低要求是:
- 需要捕获表达式文本。(我知道如何使用宏执行此操作)
- 只需要一个包装器名称空间,因为我不希望意外使用错误的包装器损坏我的日志,或者可能导致隐式转换,从而可能更改包装表达式的预期行为
- 包装器必须返回/强制转换嵌套表达式的确切类型,或者换句话说,不影响嵌套表达式的确切预期行为
type:“bool”
&type:“QString”
,这很好,但不是必需的
我希望这一切都有意义。谢谢。基本方法不是使用
QVariant
,而是使用一个模板,返回相同类型的表达式值:
#define LOG(EXPR) (log(#EXPR, EXPR))
void log(const std::string &); // logging function
std::string demangle(const char*); // demangler - see below
template <typename T> T log(const char * expr, T &&value) {
auto const &type = std::typeid(value);
std::ostringstream os;
os << "expression \" << expr << "\" = (" << value << ") type: "
<< demangle(type.name());
log(os.str());
return std::forward(value);
}
你是想问我什么?它的实现已定义,可能会被破坏。否则,您需要将
typeid(EXPR)
生成的std::type_info
对象转换为一个漂亮的字符串。或者,特别是对于Qt,只需对value参数调用QVariant::typeName()。类型名称对于日志记录来说很好,但最终的目标是一个包装器,它将包装表达式,记录它们,但不会阻止表达式发挥作用。例如,if(path.isEmpty()){}
如果我执行if(LOG(path.isEmpty()){}
操作,那么它的功能应该与QString path=LOG(QDir::currentPath())的功能相同代码>我处理过它。我必须将QLatin1Strings
替换为QStrings
,才能进行编译。不确定这是否有什么大不了的。。。我不能调用std::typeid
,而只能执行typeid
,并返回std::forward(值)代码>变为<代码>返回标准::前进(值)代码>--它似乎工作得很顺利。非常感谢。
#ifdef __GNUG__
#include <cxxabi.h>
#include <memory>
std::string demangle(const char *name) {
int status;
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return {(status==0) ? res.get() : name};
}
#else
std::string demangle(const char *name) {
return {name};
}
#endif
void log(const QString &); // logging function
QString demangle(QLatin1String); // demangler - see below
template <typename T> T log(QLatin1String expr, T &&value) {
auto const type = demangle(std::typeid(value).name());
log(QStringLiteral("expression \"%1\" = (%2) type: %3")
.arg(expr).arg(value).arg(type));
return std::forward(value);
}
#ifdef __GNUG__
#include <cxxabi.h>
#include <memory>
QString demangle(QLatin1String name) {
int status;
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name.latin1(), NULL, NULL, &status),
std::free
};
return {(status==0) ? QLatin1String(res.get()) : name};
}
#else
QString demangle(QLatin1String name) { return {name}; }
#endif