typedef と C++ での使用:よりクリーンなコードへの 2 つの方法
目次 :
<オール>はじめに
この記事では、C++ の 2 つの型エイリアス (typedef と using) の違いについて説明します。
- 簡単に言うと、int などの既存の型の名前を Photo に変更します。
明確で簡潔で理解しやすいコードを作成するのに役立ちます。
次の例を考えてみましょう。
ライブラリでの作業中に、2 つの関数が作成されます
int getLength();
Photo getLength();
後者の方がより自然な選択のようです。エイリアス Photo を宣言すると、関数が何であるかが明らかになります。
繰り返しになりますが、型エイリアスは実際には新しい型を作成するわけではありません。代わりに、シノニムまたは基になるものを呼び出す別の方法を定義します。
-
ユニオン、クラスなどの新しい型宣言は、'typedef' によって導入されません。代わりに、既存の型には、他の識別子と同じ名前空間にある新しい名前が付けられます。
-
「typedef」宣言はうまく機能し、ほとんどの部分で十分でしたが、特にテンプレートの使用に関しては明らかな欠点があります。次のセクションでは、そのような制約と、「using」ステートメントがそれらにどのように対処するかを見ていきます。
エイリアスの宣言
最新の C++ のプログラマーには 2 の機能があります 新しい型エイリアスを宣言するためのオプション。
typedef キーワードは、通常の方法で新しい型エイリアスを宣言するために使用されます。
typedef [original-type] [alias];
例
typedef int Photo;
typedef std::map<std::string, std::vector<std::string>> Map;
使用 キーワードは、C++11 で導入された新しい型エイリアスを宣言する新しい手段です。
using [alias] = [original-type];
例
using Photo = int;
using Map = std::map<std::string, std::vector<std::string>>;
どちらの場合も最終結果は同じです:2 つのエイリアス Photo と地図 どこでも使用できるように形成されています。
主な違い
<オール>エイリアス マップの型は固定されています。常に
std::map<std::string, std::vector< std::string >>
になります。 std::map<int, std::vector<int>>
など、別のものに変換する方法はありません。 、その型で新しいエイリアスを宣言しない限り。C++11 を使用すると、エイリアス テンプレートを作成できます。これは、基になる型への開かれたドアを維持するエイリアスです。テンプレート パラメーターを後で定義するオプションもありながら、従来型のエイリアスを使用できます。
エイリアス テンプレートを宣言するための構文
template<[template-parameter-list]> using [alias] = [original-type];
例:
template<typename TA, typename TB> using Map = std::map<TA, std::vector<TB>>;
現在、さまざまなタイプの新しいマップ変数を以下のように定義できます:
// Actual type: std::map<std::string, std::vector<std::string>>
Map<std::string, std::string> mapA;
// Actual type: std::map<int, std::vector<int>>
Map<int, int> mapB;
// Actual type: std::map<int, std::vector<float>>
Map<int, float> mapC;
従来の typedef を使用してこの動作を再現することもできますが、はるかに困難です。
- プログラマーの観点から見ると、"using" ステートメントの操作は非常に単純で明確です。特に、関数ポインターとそのエイリアス定義を操作する場合はそうです。実際、次の例に示すように、「using」ステートメントを使用するとコードが読みやすくなります:
typedef void(*func_pointer)(int);
using func_pointer = void(*)(int);
-
'using' ステートメントと 'typedef' ステートメントの両方を使用して作成されたエイリアス宣言は、クラス、名前空間、およびブロックを含むコード内のあらゆる場所で作成できますが、'using' ステートメントのみで作成されたテンプレート宣言は、クラス内で宣言することはできません。 /P>
-
ラッピングを必要としない「using」ステートメントとは異なり、「typedef」の場合、ジェネリック エイリアスの宣言は常に構造体でラップする必要があります。
template<typename T>
using Account = std::unordered_map<Admission_No, std::vector<T>>;
Vs
template<typename T>
struct Account {
typedef std::map<Admission_No, std::vector<T>> type;
};
//Using the above like:
Account<AdmissionAccount>::type AdmissionDetailsAccount;
-
2 つの異なるファイルで typedef を使用して同じ変数を宣言することは可能であり、両方が同じ型を参照している限り、エラーはスローされません。これは、キーワードの使用では無効です。
-
「using」ステートメントとは異なり、「typedef」を使用すると、プログラマーは多数の型エイリアスを一度に指定できます。
typedef int x, *ptr, (*Fun)();
結論
より単純な型エイリアスを定義する場合は、typedef から選択します 使用 個人の選択の問題かもしれません。 typedef の主な制限 テンプレートでは機能しないということです。両方使用 およびtypedef 非テンプレートでの作業中に同じことを機械的に実行します。ただし、より複雑なテンプレート エイリアス、関数ポインタ エイリアス、および配列参照エイリアスを定義している間、using 声明は明らかな勝者として現れます.
OpenGenus のこの記事を読むと、typedef と C++ での使用の完全なアイデアが得られます。