Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
30
Help us understand the problem. What is going on with this article?
@_EnumHack

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

More than 5 years have passed since last update.

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

テンプレートを記述していると
「この引数を与えたときには、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&&){}
                     ^

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

30
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
_EnumHack
迷えるC++プログラマを救う神様をやっています。
caddi
製造業の受発注プラットフォーム「CADDi」を提供しています。 モノづくりに携わるすべての人が、本来持っている力を最大限に発揮できる社会を実現する。産業の常識を変える「新たな仕組み」をつくります。 「CADDi」は金属加工品のCAD・設計図の解析から複雑な物流を表現するUIまで幅広い開発をしており、常に開発環境に最新の技術をとり入れて、より良いプロダクトを作るように心がけております。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
30
Help us understand the problem. What is going on with this article?