私の長年のC++(MFC)プログラミングでは、typedef
を使用する必要性を感じたことはなかったので、何に使用されているのかわかりません。どこで使用すればよいですか? typedef
の使用が推奨される実際の状況はありますか?または、これは本当にC固有のキーワードですか?
typedef
はnecessary多くの テンプレートメタプログラミング タスク-クラスが「コンパイルtypedef
は、結果型を取得するための「コンパイル時型値」として使用されます。例えば。ポインター型をその基本型に変換するための単純なメタ関数を考えてみましょう。
template<typename T>
struct strip_pointer_from;
template<typename T>
struct strip_pointer_from<T*> { // Partial specialisation for pointer types
typedef T type;
};
例:型式strip_pointer_from<double*>::type
はdouble
と評価されます。テンプレートのメタプログラミングは、ライブラリ開発以外では一般的に使用されないことに注意してください。
typedef
はhelpfulで、複雑な関数ポインター型に短くて明確なエイリアスを与えるためのものです。
typedef int (*my_callback_function_type)(int, double, std::string);
void RegisterCallback(my_callback_function_type fn) {
...
}
Bjarneの本では、整数のサイズが異なるシステム間の移植性の問題にtypedefを使用して対処できると述べています。 (これは言い換えです)
sizeof(int)
が4のマシンでは、次のことができます。
_typedef int int32;
_
次に、コードのすべての場所で_int32
_を使用します。 sizeof(int)
が2であるC++の実装に移行する場合、typdef
を変更するだけです。
_typedef long int32;
_
プログラムは引き続き新しい実装で動作します。
関数ポインターで使用
Typedefを使用して関数ポインター宣言を非表示にする
void (*p[10]) (void (*)() );
Pが「voidを返す関数への10個のポインターの配列であり、voidを返し、引数をとらない別の関数へのポインターを取得する」ことを知ることができるプログラマーはほとんどいません。面倒な構文はほとんど判読できません。ただし、typedef宣言を使用することで大幅に簡素化できます。まず、次のように「voidを返し、引数を取らない関数へのポインタ」のtypedefを宣言します。
typedef void (*pfv)();
次に、以前に宣言したtypedefに基づいて、「voidを返し、pfvを受け取る関数へのポインター」の別のtypedefを宣言します。
typedef void (*pf_taking_pfv) (pfv);
扱いにくい「voidを返し、pfvを取得する関数へのポインター」の同義語としてpf_taking_pfv typedefを作成したので、このような10個のポインターの配列を宣言するのは簡単です。
pf_taking_pfv p[10];
言われたことのいくつかの例を提供するために:STLコンテナー。
typedef std::map<int,Froboz> tFrobozMap;
tFrobozMap frobozzes;
...
for(tFrobozMap::iterator it=frobozzes.begin(); it!=map.end(); ++it)
{
...
}
次のようなtypedefを使用することも珍しくありません
typedef tFrobozMap::iterator tFrobozMapIter;
typedef tFrobozMap::const_iterator tFrobozMapCIter;
別の例:共有ポインターの使用:
class Froboz;
typedef boost::shared_ptr<Froboz> FrobozPtr;
[更新]コメント通り-それらをどこに置くか?
最後の例-shared_ptr
を使用するのは簡単です:本当のヘッダー素材です-少なくともフォワードヘッダーです。とにかくshared_ptrの前方宣言が必要です。その宣言された利点の1つは、前方宣言で安全に使用できることです。
別の言い方をすれば、shared_ptrがある場合は、shared_ptrを介してのみ型を使用する必要があるため、宣言を分離してもあまり意味がありません。
(はい、xyzfwd.hは苦痛です。ホットスポットでのみ使用します-ホットスポットを特定するのは難しいことを知っています。C++コンパイル+リンクモデルを非難します...)
私は通常、コンテナ変数が宣言されている場所で使用するコンテナタイプ定義-例えば実際のコンテナインスタンスがクラスメンバである場合、ローカルvarの場合はローカル、クラスメンバとして。実際のコンテナタイプが実装の詳細である場合、これはうまく機能します-追加の依存関係を引き起こしません。
それらがparticularインターフェースの一部になる場合、使用されるインターフェースとともに宣言されます。
// FrobozMangler.h
#include "Froboz.h"
typedef std::map<int, Froboz> tFrobozMap;
void Mangle(tFrobozMap const & frobozzes);
タイプが異なるインターフェイス間のバインディング要素である場合、つまり、複数のヘッダーで同じタイプが必要な場合、問題が生じます。いくつかの解決策:
後者の2つはそれほど優れていないことに同意します。トラブルに直面したときにのみ(積極的にではなく)使用します。
typedefは多くの状況で役立ちます。
基本的に、型のエイリアスを作成できます。タイプを変更する必要がある場合、または変更する必要がある場合、残りのコードは変更されない可能性があります(もちろん、コードによって異なります)。たとえば、C++ベクトルを反復処理するとします。
vector<int> v;
...
for(vector<int>::const_iterator i = v->begin(); i != v.end(); i++) {
// Stuff here
}
将来的には、リストでベクトルを変更することを考えるかもしれません。なぜなら、あなたがそれに対してしなければならない操作のタイプだからです。 typedefを使用しないと、コード内のすべてのベクトルの発生を変更する必要があります。しかし、次のようなものを書く場合:
typedef vector<int> my_vect;
my_vect v;
...
for(my_vect::const_iterator i = v->begin(); i != v.end(); i++) {
// Stuff here
}
これで、1行のコードを変更するだけです(つまり、「typedef vector<int> my_vect
"から" typedef list<int> my_vect
")そしてすべてが機能します。
typedefは、書き込みが非常に長い(そして読みにくい)複雑なデータ構造がある場合にも時間を節約します
Typedefを使用する理由の1つは、何かのタイプが変更される可能性がある場合です。たとえば、現時点では、一部のデータセットのインデックス化には16ビットintが適しているとしましょう。予見できる将来のために、65535個未満のアイテムがあり、スペースの制約が大きいか、キャッシュのパフォーマンスが優れている必要があるからです。ただし、65535を超えるアイテムを持つデータセットでプログラムを使用する必要がある場合は、より広い整数に簡単に切り替えられるようにする必要があります。 typedefを使用すると、これを1か所で変更するだけで済みます。
typedef
は、複雑な型のエイリアスを持つだけでなく、型を文書化するための自然な場所を提供します。私は時々文書化の目的でそれを使用します。
バイト配列を使用することもあります。現在、バイトの配列は多くのことを意味する可能性があります。 typedef
は、バイト配列を「hash32」または「fileContent」として定義してコードを読みやすくするのに便利です。
Typedefを使用するもう1つのユースケースは、一種のContainer Independent code(ただし正確ではありません!)を有効にする場合です。
クラスがあるとしましょう:
Class CustomerList{
public:
//some function
private:
typedef list<Customer> CustomerContainer;
typedef CustomerContainer::iterator Cciterator;
};
上記のコードは、typedefを使用して内部コンテナー実装をカプセル化します。将来、リストコンテナーをベクターまたはデックに変更する必要がある場合でも、CustomerListクラスのユーザーは正確なコンテナー実装を心配する必要はありません。
したがって、typedefはカプセル化され、コンテナに依存しないコードを書くのにいくらか役立ちます
Typedefの実際の使用:
タイプにローカルラベルを提供します。例:
template<class _T> class A
{
typedef _T T;
};
template<class _T> class B
{
void doStuff( _T::T _value );
};
ソースが明確になるか、読みやすくなるたびに。
ジェネリック/テンプレートには、C#で一種のtypedefを使用します。 「NodeMapping」は、多くの「Dictionary <string、XmlNode>」を読んだり使用したり理解したりするのに適しています。私見では。そのため、テンプレートにそれをお勧めします。
Typedefを使用すると、クラスの柔軟性が高まります。プログラムでデータ型を変更する場合、複数の場所を変更する必要はなく、1回だけ変更する必要があります。
typedef <datatype example int or double> value_type
value_type
の代わりにnay名を付けることができますが、通常はvalue_type
が標準名です。
したがって、次のようにtypedefを使用できます。
value_type i=0; //same as a int or double i=0;