背景故事(您可以跳过)

在尽我所能提出问题时,我得知#define宏的第二个括号不是我想的那样是return,而是实际上是cast。据我所知,捕获表达式文本的唯一方法是使用#define宏。棘手的部分,也许是不可能的,是捕获显式type的文本,但是我知道什么?

也;我将其指定给Qt而不是C ++ / gcc的原因是,我认为解决方案可能涉及类似QVariant的类,该类增加了一些多态性,但是这并不理想,因为很难区分某些基本类型,例如int vs bool

我希望实现的目标

基本上,我想要一个包装器,我猜是一个宏,它将记录嵌套的表达式文本,其值,并返回其确切的嵌套类型(无隐式转换)。

例如:

/* 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);
}


可以从this answer改编分解器:

#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


如果要使用Qt类型,请使用QString而不是std::string

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

关于c++ - 在Qt/GCC/C++中;如何创建一个包装器,该包装器既可以捕获参数表达式文本,又可以返回/传递参数的显式类型?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49323810/

10-15 17:19