2014年9月21日日曜日

C++11で型の名前を出す方法

さて、templateなんかが一杯くっつき始めると、
_Tpなんて出てくる型が何の型かさっぱり……
となってしまいます。

便利な型名のダンプルーチンがPrint variable type in C++にあったので引用。
#include <type_traits>
#include <typeinfo>
#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;
}
これを、type_name.hなんてファイルにしておいて、
#include <type_name.h>
...
  std::cout << "type " << type_name<_Tp>() << std::endl;
なんてするだけで型名がダンプできて便利。変数に対してやるときは、
...type_name<decltype(a)>()...
と使います。

以下に実例追記



typeid(i).name()との比較で示すと、末尾のTPを動かすと、こう出力されます。
### int ###
typeid.name: i, type_name: int

### const int ###
typeid.name: i, type_name: int const

### std::string ###
typeid.name: Ss, type_name: std::string

### const std::string& ###
typeid.name: Ss, type_name: std::string const&

### const std::string&& ###
typeid.name: Ss, type_name: std::string const&&

とても便利。これ大事


以下、TPのソースです。
#include <iostream>
#include "type_name.h"

main()
{
    int i = 1;
    std::cout << "### int ###" << std::endl;
    std::cout << "typeid.name: " << typeid(i).name()
    << ", type_name: " << type_name<decltype(i)>() << std::endl << std::endl;
    const int ci = 1;
    std::cout << "### const int ###" << std::endl;
    std::cout << "typeid.name: " << typeid(ci).name()
    << ", type_name: " << type_name<decltype(ci)>() << std::endl << std::endl;
    std::string s = "hello";
    std::cout << "### std::string ###" << std::endl;
    std::cout << "typeid.name: " << typeid(s).name()
    << ", type_name: " << type_name<decltype(s)>() << std::endl << std::endl;
    const std::string& csr = s;
    std::cout << "### const std::string& ###" << std::endl;
    std::cout << "typeid.name: " << typeid(csr).name()
    << ", type_name: " << type_name<decltype(csr)>() << std::endl << std::endl;
    const std::string&& csrr = std::string("test");
    std::cout << "### const std::string&& ###" << std::endl;
    std::cout << "typeid.name: " << typeid(csrr).name()
    << ", type_name: " << type_name<decltype(csrr)>() << std::endl << std::endl;
}
便利、便利

0 件のコメント:

コメントを投稿