在编译时打印模板typename

Gab*_*ern 34 c++ g++

在C++中创建模板函数时,有一种简单的方法可以将模板的类型名称表示为字符串吗?我有一个简单的测试用例来展示我正在尝试做的事情(注意显示的代码不能编译):

#include <stdio.h>
template <typename type>
type print(type *addr) 
{
  printf("type is: %s",type);
}

int main()
{
  int a;
  print(&a);
}

// Would like to print something like:
// type is: int
Run Code Online (Sandbox Code Playgroud)

我认为在实例化函数时,typename应该在编译时可用,但我不熟悉模板,我还没有看到将typename作为字符串的方法.

我想这样做的原因是一些printf类型的调试.我有多个线程正在运行,并通过gdb逐步更改程序行为.所以对于某些事情,我想转储有关正在执行哪些函数的信息.这不是太重要,所以如果解决方案过于复杂,我会跳过将此信息添加到我的日志记录功能中.但如果有一种简单的方法可以做到这一点,那将是有用的信息.

mat*_*tiu 59

要获得有用的编译时名称:

假设你有一些名为'T'的未知类型.你可以让编译器通过使用它来打印它的类型.例如:

typedef typename T::something_made_up X;
Run Code Online (Sandbox Code Playgroud)

错误消息将如下:

error: no type named 'something_made_up' in 'Wt::Dbo::ptr<trader::model::Candle>'
Run Code Online (Sandbox Code Playgroud)

'in'后面的位显示类型.(仅用clang测试过).

触发它的其他方式:

bool x = T::nothing;   // error: no member named 'nothing' in 'Wt::Dbo::ptr<trader::model::Candle>'
using X = typename T::nothing;  // error: no type named 'nothing' in 'Wt::Dbo::ptr<trader::model::Candle>'
Run Code Online (Sandbox Code Playgroud)

使用C++ 11,您可能已经有了一个对象并使用'decltype'来获取其类型,因此您还可以运行:

auto obj = creatSomeObject();
bool x = decltype(obj)::nothing; // (Where nothing is not a real member). 
Run Code Online (Sandbox Code Playgroud)

  • 当你有没有编译的代码时,这真的有助于在编译时打印类型名称! (5认同)
  • 实际回答问题的唯一回应! (2认同)
  • 与`gcc`一起使用也很好. (2认同)
  • 恕我直言,这个应该是一个公认的答案 (2认同)

Dav*_*d D 22

__PRETTY_FUNCTION__ 应该解决你的问题(至少在运行时)

以下程序的输出是:

asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf test<type>::test() [with type = int]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
asfdasdfasdf void tempFunction() [with type = bool]
!!!Hello World!!!
Run Code Online (Sandbox Code Playgroud)

如果你确实需要将typename作为字符串,你可以破解它(使用snprintf而不是printf)并在'='之后和']'之前拉出子字符串.

#include <iostream>
using namespace std;

template<typename type>
class test
{
public:
test()
{
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
}
};

template<typename type>
void tempFunction()
{
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
    printf("asfdasdfasdf %s\n", __PRETTY_FUNCTION__);
}

int main() {
    test<int> test;

    tempFunction<bool>();
    cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @kuhaku只有在使用支持__PRETTY_FUNCTION__的编译器时才会编译.[查看此答案以查看有关__PRETTY_FUNCTION__的详细信息](http://stackoverflow.com/questions/4384765/whats-the-difference-between-pretty-function-function-func).另外[此链接](https://msdn.microsoft.com/library/b0084kay.aspx)将向您展示可以使用哪些Windows宏来执行相同的操作.我怀疑__func__会起作用,但没有尝试或试图确认.我专门使用GCC,所以我没有确认的环境. (2认同)
  • 不是编译时 (2认同)

ipc*_*ipc 11

既然你已经说过你需要这个用于调试目的,也许运行时解决方案也是可以接受的.并且您已将其标记为g ++,因此您不希望成为标准符合.

这意味着什么:

#include <cxxabi.h> // the libstdc++ used by g++ does contain this header

template <typename type>
void print(const type *addr) // you wanted a pointer
{
  char * name = abi::__cxa_demangle(typeid(*addr).name(), 0, 0, NULL);
  printf("type is: %s\n", name);
  delete name;
}

print(new unsigned long);    // prints "type is: unsigned long"
print(new std::vector<int>); // prints "type is: std::vector<int, std::allocator<int> >"
Run Code Online (Sandbox Code Playgroud)

编辑:纠正了内存泄漏.谢谢杰西.

  • 这在编译时不起作用,它只是打印出被破坏的名称 (2认同)

flo*_*tan 10

另一种编译时解决方案,类似于matiu提供的解决方案,但也许更具描述性的是使用static_assert包装在一个小辅助函数中:

template <typename T>
void print_type_in_compilation_error(T&&)
{
    static_assert(!std::is_same<T, int>::value &&
                   std::is_same<T, int>::value,
                  "Compilation failed because you wanted to know the type; see below:");
}
Run Code Online (Sandbox Code Playgroud)
// usage:
int I;
print_type_in_compilation_error(I);
Run Code Online (Sandbox Code Playgroud)

以上会给你一个很好的错误消息(在 MSVC 和 Clang 中测试),就像在另一个答案中一样,但我认为代码更容易理解。


And*_*rey 6

有Boost.TypeIndex库.

有关详细信息,请参阅boost :: typeindex :: type_id.

它非常易于使用,跨平台,是真正的编译型解决方案.即使没有可用的RTTI,它也可以正常工作.此外,大多数编译器都是从盒子中支持的.