Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 取消混合std::type_info::name的结果_C++_Gcc_Name Mangling_Clang_Msvc_C++17 - Fatal编程技术网

C++ 取消混合std::type_info::name的结果

C++ 取消混合std::type_info::name的结果,c++,gcc,name-mangling,clang,msvc,c++17,C++,Gcc,Name Mangling,Clang,Msvc,C++17,我目前正在编写一些日志代码,其中包括打印有关调用函数的信息。这应该比较容易,标准C++有一个 Type信息> /Cuff>类。它包含typeid的类/函数/等的名称,但已损坏。这不是很有用。例如,typeid(std::vector).name()返回st6vectorisaiee 有没有办法从中产生有用的东西?对于上述示例,类似于std::vector。如果它只适用于非模板类,那也可以 这个解决方案应该适用于gcc,但是如果我可以移植它,那就更好了。它是用来记录日志的,所以它不是很重要,不能关

我目前正在编写一些日志代码,其中包括打印有关调用函数的信息。这应该比较容易,标准C++有一个<代码> Type信息> /Cuff>类。它包含typeid的类/函数/等的名称,但已损坏。这不是很有用。例如,
typeid(std::vector).name()
返回
st6vectorisaiee

有没有办法从中产生有用的东西?对于上述示例,类似于
std::vector
。如果它只适用于非模板类,那也可以


这个解决方案应该适用于gcc,但是如果我可以移植它,那就更好了。它是用来记录日志的,所以它不是很重要,不能关闭,但它应该有助于调试。

它是由实现定义的,所以它不是可移植的。在MSVC++中,name()是未修饰的名称,您必须查看原始名称()才能得到修饰的名称。

这里只是一个暗箱操作,但在gcc下,您可能想看看

我一直想使用type_info,但我确信name()成员函数的结果是非标准的,不一定会返回任何可以转换为有意义的结果。

如果您坚持使用一个编译器,那么可能有一个特定于编译器的函数可以实现您想要的功能。查看文档。

查看
\uuucxa\u demangle
,您可以在
cxxabi.h
中找到这是我们使用的。HAVE_CXA_DEMANGLE仅在可用时设置(仅限GCC的最新版本)


这不是一个完整的解决方案,但您可能希望了解一些标准(或广泛支持的)宏的定义。在日志代码中,查看宏的使用是很常见的:

__FUNCTION__
__FILE__
__LINE__

e.g.:

log(__FILE__, __LINE__, __FUNCTION__, mymessage);
在这里,看一看它包含一个函数,它可以实现您想要的功能


如果您只是寻找一个Demanling工具,例如,您可以使用它来处理日志文件中显示的内容,那么请查看binutils附带的
c++filt
。它可以分解C++和java符号名。

我也发现了一个宏叫做“代码>”它给出了一个漂亮的函数名(图:)。这就是我需要的

也就是说,它给了我以下信息:

virtual bool mutex::do_unlock()
但我认为它在其他编译器上不起作用。

//KeithB的解决方案很好,但有一个严重的缺陷,除非buf是静态的
// KeithB's solution is good, but has one serious flaw in that unless buf is static
// it'll get trashed from the stack before it is returned in res - and will point who-knows-where
// Here's that problem fixed, but the code is still non-re-entrant and not thread-safe.
// Anyone care to improve it?

#include <cxxabi.h>

// todo: javadoc this properly
const char* demangle(const char* name)
{
    static char buf[1024];
    size_t size = sizeof(buf);
    int status;
    // todo:
    char* res = abi::__cxa_demangle (name,
                                 buf,
                                 &size,
                                 &status);
    buf[sizeof(buf) - 1] = 0; // I'd hope __cxa_demangle does this when the name is huge, but just in case.
    return res;
  }
//在以res返回之前,它将从堆栈中被丢弃,并且将指向谁知道在哪里 //这个问题已经解决了,但是代码仍然是不可重入的,并且不是线程安全的。 //有人想改进吗? #包括 //todo:javadoc正确地描述了这一点 常量字符*demangle(常量字符*名称) { 静态字符buf[1024]; 尺寸=尺寸(buf); 智力状态; //待办事项: char*res=abi::\uuucxa\udemangle(名称, 缓冲器, &大小, &地位); buf[sizeof(buf)-1]=0;//我希望uu cxa\u demangle在名称庞大时会这样做,但以防万一。 返回res; }
考虑到这个问题/答案受到的关注和来自的宝贵反馈,我已经稍微整理了一下代码。给出了两个版本:一个具有C++11特性,另一个仅具有C++98特性

在文件中键入.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());
}
*/

class Typeid {
 public:

  template <class T>
    Typeid(const T& t) : typ(typeid(t)) {}

  std::string name() { return demangle(typ.name()); }

 private:
  const std::type_info& typ;
};


#endif
\ifndef型水电站
#定义HPP类型
#包括
#包括
std::string demangle(const char*name);
模板
标准::字符串类型(常量T&T){
返回demangle(typeid(t).name());
}
#恩迪夫
在文件中键入.cpp(需要C++11)

#包括“type.hpp”
#ifdef_u_GNUG__
#包括
#包括
#包括
std::string demangle(常量字符*名称){
int status=-4;//消除编译器警告的任意值
//通过将标志-std=c++11传递给g来启用c++11++
标准::唯一的\u ptr res{
abi::_cxa_demangle(名称、空值、空值和状态),
免费
};
return(status==0)?res.get():name;
}
#否则
//如果没有g什么都不做++
std::string demangle(常量字符*名称){
返回名称;
}
#恩迪夫
用法:

#包括
#包括“类型.hpp”
结构Base{virtual~Base(){};
派生结构:公共基{};
int main(){
Base*ptr_Base=new-Derived();//请在代码中使用智能指针!

std::cout对Ali的解决方案有一点不同。如果您希望代码仍然与

typeid(bla.name()

改写这个

Typeid(bla.name()
(只在大写首字母上有所不同)

那么您可能会对此感兴趣:

在文件中键入.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());
}
*/

class Typeid {
 public:

  template <class T>
    Typeid(const T& t) : typ(typeid(t)) {}

  std::string name() { return demangle(typ.name()); }

 private:
  const std::type_info& typ;
};


#endif
\ifndef型水电站
#定义HPP类型
#包括
#包括
std::string demangle(const char*name);
/*
模板
标准::字符串类型(常量T&T){
返回demangle(typeid(t).name());
}
*/
类类型ID{
公众:
模板
Typeid(const T&T):类型(Typeid(T)){}
std::string name(){return-demangle(typ.name());}
私人:
常数标准::类型信息和类型;
};
#恩迪夫

类型。cpp与阿里的解决方案保持一致

Boost core包含demangler。签出:

#包括
#包括
#包括
模板结构X
{
};
int main()
{
char const*name=typeid(X).name();
std::cout这个[1]工作得很好。
我发现至少有一个案例(我不会称之为角落案例)没有报告我所期望的情况…有参考资料

对于这些情况,我找到了另一个解决方案,张贴在底部

问题案例(使用[1]中定义的
类型
):

解决方案(使用
键入\u name()
,请参见下面的代码):

如所愿(至少由我)

代码 . 由于专门化问题,它必须位于包含的头文件中,而不是单独编译的源文件中

#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>

template <class T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}
\ifndef\u MSC\u VER
#包括
#恩迪夫
#包括
#包括
#包括
模板
int i = 1;
cout << "Type of " << "i" << " is " << type(i) << endl;
int & ri = i;
cout << "Type of " << "ri" << " is " << type(ri) << endl;
Type of i is int
Type of ri is int
cout << "Type of " << "i" << " is " << type_name<decltype(i)>() << endl;
cout << "Type of " << "ri" << " is " << type_name<decltype(ri)>() << endl;
Type of i is int
Type of ri is int&
#ifndef _MSC_VER
#   include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>

template <class T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
#ifndef _MSC_VER
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
#else
                nullptr,
#endif
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}
std::__cxx11::basic_string<char>
std::basic_string<char>