web-dev-qa-db-ja.com

C++ 11の 'typedef'と 'using'の違いは何ですか?

C++ 11ではusingsのようにtypedefを使って別名型を書くことができるようになりました。

typedef int MyInt;

私が理解していることから、次のものと同等です。

using MyInt = int;

そして、その新しい構文は "template typedef"を表現する方法を持つ努力から生まれました:

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

しかし、最初の2つのテンプレート以外の例では、標準に他の微妙な違いはありますか?たとえば、typedefsは「弱い」方法でエイリアシングを行います。つまり、新しい型は作成されず、新しい名前のみが作成されます(これらの名前間の変換は暗黙的です)。

usingと同じですか、それとも新しい型を生成しますか?違いはありますか?

781
Klaim

それらは、標準(強調鉱山)からは同等です(7.1.3.2)。

型定義名は、別名宣言によっても導入できます。 usingキーワードに続く識別子はtypedef-nameになり、識別子に続くオプションのattribute-specifier-seqはそのtypedef-nameに関連付けられます。 typedef指定子によって導入された場合と同じ意味を持ちます。 特に、それは新しい型を定義せず、それはtype-idに現れてはならない。

511
Jesse Good

using 構文は、テンプレート内で使用すると利点があります。型の抽象化が必要だが、将来指定できるようにテンプレートパラメータを保持する必要がある場合あなたはこのようなものを書くべきです。

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // to make it possible to substitue the whatever in future.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

しかし using という構文は、この使用例を単純化します。

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }
180
4xy

それ以外は、ほとんど同じです。

エイリアス宣言はテンプレートと互換性がありますが、Cスタイルのtypedefは互換性がありません。

172
Zhongming Qu

それらは本質的に同じですが、usingalias templatesを提供します。これは非常に便利です。私が見つけることができた一つの良い例は以下の通りです:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

そのため、std::add_const_t<T>の代わりにtypename std::add_const<T>::typeを使用できます。

22
Validus Oculus

元のポスターには素晴らしい答えがあることは知っていますが、このスレッドにつまずいた人には、 提案 からの重要なメモがあります。 typedefキーワードが将来非推奨としてマークされるか、冗長/古いため削除されるかについてのコメント:

キーワードtypedef ...を(再)使用して、テンプレートエイリアスを導入することが推奨されています。

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

その表記法には、タイプエイリアスを導入することが既に知られているキーワードを使用するという利点があります。ただし、いくつかの欠点も表示されます。その中には、タイプではなくテンプレートを指定するコンテキストで、タイプ名のエイリアスを導入することが知られているキーワードの使用の混乱があります。 Vecnot型のエイリアスであり、typedef-nameには使用しないでください。名前Vecはファミリーの名前ですstd::vector<•, MyAllocator<•> > –ここで、箇条書きはtype-nameのプレースホルダーです。そのため、「typedef」構文は提案しません。

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

これから読み、解釈できます。Vec<T>std::vector<T, MyAllocator<T> >の同義語として使用します。そのように読めば、エイリアシングの新しい構文は合理的であるように思えます。

私にとって、これは、C++でtypedefキーワードを引き続きサポートすることを意味します。これは、コードをさらに読みやすく、理解しやすくすることができるからです

usingキーワードの更新はテンプレート専用であり、(受け入れられた回答で指摘されているように)非テンプレートで作業している場合はusingtypedefは機械的に同一なので、選択は読みやすさと意図のコミュニケーションを理由にプログラマー次第です。

3
RoboticForest