- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我目前正在编写一些日志代码,这些代码应该——除其他外——打印有关调用函数的信息。这应该比较容易,标准C++有一个type_info
类(class)。这包含 typeid 的类/函数/等的名称。但它被破坏了。它不是很有用。 IE。 typeid(std::vector<int>).name()
返回 St6vectorIiSaIiEE
.
有没有办法从中产生有用的东西?点赞std::vector<int>
对于上面的例子。如果它只适用于非模板类,那也没关系。
该解决方案应该适用于 gcc,但如果我能移植它会更好。它是用来记录的,所以它不是很重要,不能关闭,但它应该有助于调试。
最佳答案
鉴于此问题/答案受到的关注,以及来自 GManNickG 的宝贵反馈,我已经稍微清理了代码。提供了两个版本:一个具有 C++11 特性,另一个具有 C++98 特性。
在文件 type.hpp
#ifndef TYPE_HPP
#define TYPE_HPP
#include <string>
#include <typeinfo>
std::string demangle(const char* name);
template <class T>
std::string type(const T& t) {
return demangle(typeid(t).name());
}
#endif
在文件 type.cpp 中(需要 C++11)
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
用法:
#include <iostream>
#include "type.hpp"
struct Base { virtual ~Base() {} };
struct Derived : public Base { };
int main() {
Base* ptr_base = new Derived(); // Please use smart pointers in YOUR code!
std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;
std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;
delete ptr_base;
}
打印出来:
ptr_base 类型:Base*
指针类型:Derived
在 Linux 64 位和 g++ 4.7.2(Mingw32、Win32 XP SP2)上使用 g++ 4.7.2、g++ 4.9.0 20140302(实验性)、clang++ 3.4(主干 184647)、clang 3.5(主干 202594)进行测试。
如果你不能使用 C++11 的特性,这里是在 C++98 中可以做到的,文件 type.cpp 现在是:
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
struct handle {
char* p;
handle(char* ptr) : p(ptr) { }
~handle() { std::free(p); }
};
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );
return (status==0) ? result.p : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
(2013 年 9 月 8 日更新)
The accepted answer (as of Sep 7, 2013) ,当对 abi::__cxa_demangle()
的调用成功时,返回一个指向本地堆栈分配数组的指针...哎哟!
另请注意,如果您提供缓冲区,abi::__cxa_demangle()
假定它是在堆上分配的。在堆栈上分配缓冲区是一个错误(来自 gnu 文档):“如果 output_buffer
不够长,则使用 realloc
对其进行扩展。” 在指向堆栈的指针上调用 realloc()
...哎呀! (另见 Igor Skochinsky 的善意评论。)
您可以轻松验证这两个错误:只需将已接受答案(截至 2013 年 9 月 7 日)中的缓冲区大小从 1024 减小到更小的值,例如 16,并给它命名为 not 长于 15 (因此 realloc()
被 不 调用)。尽管如此,根据您的系统和编译器优化,输出将是:垃圾/无/程序崩溃。
要验证第二个错误:将缓冲区大小设置为 1,并使用名称超过 1 个字符的名称调用它。当你运行它时,程序几乎肯定会崩溃,因为它尝试使用指向堆栈的指针调用 realloc()
。
(2010 年 12 月 27 日的旧答案)
对 KeithB's code 的重要更改: 缓冲区必须由 malloc 分配或指定为 NULL。 不要在堆栈上分配它。
检查该状态也是明智之举。
我找不到 HAVE_CXA_DEMANGLE
。我检查了 __GNUG__
虽然这并不能保证代码甚至可以编译。谁有更好的主意?
#include <cxxabi.h>
const string demangle(const char* name) {
int status = -4;
char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
const char* const demangled_name = (status==0)?res:name;
string ret_val(demangled_name);
free(res);
return ret_val;
}
关于c++ - 解开 std::type_info::name 的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/281818/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!