デジタルちんぶろぐ

デジタルな話題

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  268  : 記事  0  : コメント  4419  : トラックバック  79

ニュース


技術以外は
ちんぶろぐ

記事カテゴリ

書庫

日記カテゴリ

元ネタ

 

仕事ではCばっかだし、最近C++ってあんまり触ってないなぁ。boost::call_traitsのソースを見たので横浜に向けてお勉強。

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

//
// 渡された型のサイズで値と参照を切り替える
//
template<typename T, bool sw> struct type_switcher_helper { typedef const T type; };
template<typename T> struct type_switcher_helper<T, false> { typedef const T& type; };
template<typename T> struct type_switcher {
    typedef typename type_switcher_helper<T, sizeof(T) <= sizeof(void*)>::type type;
};

//
// 型名を取得する
// 参照は値と判別できない名前を返すので特殊化する
//
template<typename T> struct get_type { static string name() { return string(typeid(T).name()); }};
template<typename T> struct get_type<T&> { static string name() { return string(typeid(T).name()) + string("&"); }};
//
template<typename T> void print_type_name() { cout << get_type<T>::name() << endl; }

//
// ポインタ判定
//
char is_pointer_helper(bool, const void* p);
int  is_pointer_helper(bool, ...);

// 関数によるポインタ判定
template<typename T> bool is_pointer_func(T a)
{
    return sizeof(is_pointer_helper(true, a)) == sizeof(char);
}

template<typename T> struct is_pointer_st { enum { Kind = 0 }; };
template<typename T> struct is_pointer_st<T*> { enum { Kind = 1 }; };

template<typename T> struct is_pointer_st<T* const> { enum { Kind = 1 }; };

int main()
{
    cout << "--- Type name  ---" << endl;
    print_type_name<int>();
    print_type_name<int*>();
    print_type_name<int&>();
    print_type_name<const int*>();
    print_type_name<volatile int*>();
    print_type_name<vector<int> >();
    // ここがcall_traits::param_typeと同じ事してるとこ
    print_type_name<type_switcher<int>::type >();
    print_type_name<type_switcher<vector<int> >::type >();

    int        a = 0;
    int&    b = a;

    cout << endl << "--- Type check by function ---" << endl;
    cout << (const char*) (is_pointer_func(a) ? "Pointer" : "Not pointer") << endl;
    cout << (const char*) (is_pointer_func(&a) ? "Pointer" : "Not pointer") << endl;
    cout << (const char*) (is_pointer_func(b) ? "Pointer" : "Not pointer") << endl;
    cout << (const char*) (is_pointer_func(&b) ? "Pointer" : "Not pointer") << endl;

    cout << endl << "--- Type check by struct ---" << endl;
    cout << (const char*) (is_pointer_st<int>::Kind ? "Pointer" : "Not pointer") << endl;
    cout << (const char*) (is_pointer_st<int*>::Kind ? "Pointer" : "Not pointer") << endl;
    cout << (const char*) (is_pointer_st<int&>::Kind ? "Pointer" : "Not pointer") << endl;

    return 0;
}

出力結果は以下のとおり。

VS2008

--- Type name ---
int
int *
int&
int const *
int volatile *
class std::vector<int,class std::allocator<int> >
int
class std::vector<int,class std::allocator<int> >&

--- Type check by function ---
Not pointer
Pointer
Not pointer
Pointer

--- Type check by struct ---
Not pointer
Pointer
Not pointer

 

Cygwin+GCC3.4.4

--- Type name ---
i
Pi
i&
PKi
PVi
St6vectorIiSaIiEE
i
St6vectorIiSaIiEE&

--- Type check by function ---
Not pointer
Pointer
Not pointer
Pointer

--- Type check by struct ---
Not pointer
Pointer
Not pointer

 

VS2008のtypeid().nameの名前に感動。

 

これだけだと問題があって、long longやdoubleのようなvoid*よりも大きいサイズの型だと組込型でも参照になっちゃう。

call_traitsのソースを見ると、その辺も考慮してもっときちんと書いてあるけど、これくらいのプログラムでも知りたいこと知れたからこれ以上追及はしない(ってかできないです)。

投稿日時 : 2008年8月28日 0:54

コメント

# re: templateの特殊化と型の切り替え 2008/08/28 1:56 アキラ
enumハックはもう古いですw
static const bool Kind = true; とか…

いえ、いいんですけどね

# re: templateの特殊化と型の切り替え 2008/08/28 2:21 アキラ
あぁ、GCCのtypeid(T).name()はわかんないですよねー。
メタ関数の戻り値の型をちょっと確認したいときにtypeid(T).name()で表示すると全然わからなくて、しょうがないのでis_same + static assertを使ってますw

VCでもたまにconstとか参照とか消えたりします

# re: templateの特殊化と型の切り替え 2008/08/28 14:13 う~
is_pointer_func の実装… operator T* () のようなポインタへの型変換演算子が定義されているクラスもポインタと判定されてしまうのでは?
ってつっこんでみたりして…

> あぁ、GCCのtypeid(T).name()はわかんないですよねー。
abi::__cxa_demangle() というのがあるらしいです。
http://0xcc.net/blog/archives/000095.html

# re: templateの特殊化と型の切り替え 2008/08/28 20:40 アキラ
> abi::__cxa_demangle()
おー、よさげ。

# re: templateの特殊化と型の切り替え 2008/08/28 23:48 あんどちん
> enumハックはもう古いですw
ナウい方法知らないですからw

> is_pointer_func の実装… operator T* () のようなポインタへの型変換演算子が
定義されているクラスもポインタと判定されてしまうのでは?
ご指摘ありがとうございます。その通りです。
ちょっと色気出してstruct/class以外の方法でやってみようとすると簡単にボロが出るorz

> > abi::__cxa_demangle()
> おー、よさげ。
確かに。でもgcc用にこのコードを入れるってのは抵抗が…
理想はWrite once, Compile and Run anywhereだからw
# そう言いながら毎度Windows上でしか確認してないんだよな


# re: templateの特殊化と型の切り替え 2008/08/29 11:22 う~
> 確かに。でもgcc用にこのコードを入れるってのは抵抗が…
GNU拡張ですからね~
しかも、abi::__cxa_demangle() はmallocしたメモリのアドレスを返すから、freeしないとメモリリークになるという…
私も使うのに抵抗がw

# SYPRYHnUHphqUZS 2011/12/22 20:37 http://www.discreetpharmacist.com/
sxSvWr Of course, I understand a little about this post but will try cope with it!!...

# OpTrmJHkYlRoYvrSf 2012/01/04 6:37 http://www.kosherbeefjerky.net/
6vZWDA Strange but true. Your resource is expensive. At least it could be sold for good money on its auction!...

# re: template??????????? 2021/08/08 8:56 quinine for lupus
chloroquine side effects https://chloroquineorigin.com/# hydroxcloroquine

Post Feedback

タイトル
名前
Url:
コメント: