LoginSignup
40
32

More than 5 years have passed since last update.

テンプレートの推論された型をお手軽確認

Last updated at Posted at 2016-01-21

テンプレートを書いていて、推論された型を確認したい

テンプレートを記述していると
「この引数を与えたときには、Tがどう推論されるのか?」
なんて思うことは良くありますよね?

嗚呼、そんなとき、どーしたらよいのでしょーか?

たとえば

template < typename T >
void f(T&&){}

void g(int const&){};

int main(){
    f(g);
}

この場合のTがどう推論されるのか知りたい!
と思ったとき、どうしますか?

  1. 諦める
  2. IDEに頼る
  3. typeid.name()を使う
  4. Boost.Typeindexを使う
  5. Attributeを使う(C++14)

IDEに頼る

フォーカスすると情報が表示されるのを利用する
IDEを使っている場合は概ねこれで事足りる
ET.png

typeid.name()を使う

ヘッダをインクルードして
この方法では実行時までわからない型情報を表示することができるので
RTTI(Run Time Type Identifier)と呼ばれている

#include <iostream>
#include <typeinfo>
using namespace std;

template < typename T >
void f(T&&){ cout << typeid(T).name() << endl;}

void g(int const&){};

int main(){
    f(g);
}

実行結果

FvRKiE

めでたしめでたし...

いやまて、何だこの文字列は!!

typeidで取得できる型名はそのままではマングルされていて
容易に読むことはできないのである(Microsoft コンパイラは読める文字列を返す)
デマングルするには次のようにする

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;

template < typename T >
void f(T&&){
    const type_info& id = typeid(T);
    int stat;
    char *name = abi::__cxa_demangle(id.name(),0,0,&stat);
    if( name!=NULL ) {
        if( stat==0 ) {    // ステータスが0なら成功
            printf("T = %s",name);
        }
        free(name);        // freeする必要がある
    }
}

void g(int const&){};

int main(){
    f(g);
}

Boost.Typeindex

Boost.Typeindexを使えば環境によってマングルされていたり
されていなかったりすることはないと思われる

#include <iostream>
#include <boost/type_index.hpp>
using namespace std;

template < typename T >
void f(T&&){ cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << endl;}

void g(int const&){};

int main(){
    f(g);
}

実行結果

void (&)(int const&)

めでたしめでたし...

しかし、ちょっと待てよ
これは面倒ではないか?

もっと手軽な方法がC++14には存在する

Attribute [[deprecated]]

[[deprecated]]指定してしまうのだ!
そうすれば非推奨された関数が使用されたことを悟ったコンパイラは
警告文を出す
そう、引数の型名も同時に表示してくれる!

template < typename T >
[[deprecated]] void f(T&&){}

void g(int const&){};

int main(){
    f(g);
}

警告文

prog.cc: In function 'int main()':
prog.cc:8:8: warning: 'void f(T&&) [with T = void (&)(const int&)]' is deprecated [-Wdeprecated-declarations]
     f(g);
        ^

>prog.cc:3:21: note: declared here
 [[deprecated]] void f(T&&){}
                     ^

この方法ではヘッダをインクルードすることも
デバッグ出力を書くことも
もはや必要が無い!!

40
32
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
32