[解決済み] C++のusingキーワードはどのような理屈なのでしょうか?
質問
C++のキーワード「"using"」はどのような理屈で使われているのでしょうか?
様々な場面で使用されており、私はそれを見つけようとしています。 これらには何か共通点があり、何か理由があるのでしょうか。 なぜこのようなキーワードが使われるのでしょうか?
using namespace std; // to import namespace in the current namespace
using T = int; // type alias
using SuperClass::X; // using super class methods in derived class
解決方法は?
C++11では
using
キーワードを使用した場合
type alias
と同じです。
typedef
.
7.1.3.2
typedef-nameは別名宣言で導入することもできる。その場合 using キーワードに続く識別子が typedef-nameになり、using キーワードに続く 識別子の後に続くオプションの属性指定子-seqは、その属性に属する をその型定義名と一致させる。と同じ意味合いを持つ。 はtypedef指定子によって導入される。特に,以下のものを定義しない。 は,新しい型であり,type-id に出現してはならない。
Bjarne Stroustrupが実例を示しています。
typedef void (*PFD)(double); // C style typedef to make `PFD` a pointer to a function returning void and accepting double
using PF = void (*)(double); // `using`-based equivalent of the typedef above
using P = [](double)->void; // using plus suffix return type, syntax error
using P = auto(double)->void // Fixed thanks to DyP
C++11以前では
using
キーワードは、メンバ関数をスコープに取り込むことができます。C++11では、これをコンストラクタに適用できるようになりました(Bjarne Stroustrupの別の例)。
class Derived : public Base {
public:
using Base::f; // lift Base's f into Derived's scope -- works in C++98
void f(char); // provide a new f
void f(int); // prefer this f to Base::f(int)
using Base::Base; // lift Base constructors Derived's scope -- C++11 only
Derived(char); // provide a new constructor
Derived(int); // prefer this constructor to Base::Base(int)
// ...
};
Ben Voightは、新しいキーワードや新しい構文を導入しない根拠として、かなり適切な理由を提示しています。規格は、古いコードを壊すことをできるだけ避けたいのです。このため、提案文書には次のようなセクションがあります。
Impact on the Standard
,
Design decisions
そして、それらが古いコードにどのような影響を及ぼす可能性があるかということです。ある提案が本当に良いアイデアに思えても、実装が難しすぎる、混乱しすぎる、古いコードと矛盾するなどの理由で、支持を得られない場合があるのです。
2003年の古い論文を紹介します。 n1449 . 根拠はテンプレートに関連しているようです。注意:PDFからコピーオーバーしているため、誤字脱字がある可能性があります。
<ブロッククオートまず、おもちゃのような例で考えてみましょう。
template <typename T>
class MyAlloc {/*...*/};
template <typename T, class A>
class MyVector {/*...*/};
template <typename T>
struct Vec {
typedef MyVector<T, MyAlloc<T> > type;
};
Vec<int>::type p; // sample usage
このイディオムの根本的な問題点、そして、このイディオムを採用した主な動機は この提案の理由は、このイディオムによって、テンプレート・パラメータが が非依存的な文脈で現れる。つまり を明示的に指定することなく、以下の関数fooを呼び出すことができます。 の引数を指定します。
template <typename T> void foo (Vec<T>::type&);
というわけで、やや不格好な構文になってしまいました。むしろ、ネストされた
::type
次のようなものがいい。
template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usage
特に "typedef template "という言葉を使わず、"typedef "と表記していることに注意。
using "と"="のペアを含む新しい構文を導入することで、この構文を避けることができます。
ここでは、型を定義しているわけではなく
タイプID(すなわち型)を抽象化した同義語(すなわちエイリアス)。
式)のテンプレートパラメータを含んでいます。もしテンプレート・パラメータが
が型式表現において演繹的な文脈で使用されている場合は、常に
テンプレートエイリアスがテンプレートIDを形成するために使われるとき
対応するテンプレート・パラメータを推論することができる - これについては後述する。
の後に続きます。いずれにせよ、現在では、汎用関数
を操作する
Vec<T>
を推論可能なコンテキストで提供し、構文は
も改善されました。例えば、fooを次のように書き換えることができる。
template <typename T> void foo (Vec<T>&);
を提案した主な理由の一つをここで強調しておく。
テンプレートエイリアスは、引数控除と
foo(p)
は成功する。
フォローアップ論文
n1489
の理由を説明します。
using
を使用するのではなく
typedef
:
typedefというキーワードを(再)使用することが提案されている。 論文[4] - テンプレートエイリアスを導入するために。
template<class T> typedef std::vector<T, MyAllocator<T> > Vec;
この記法は、すでに知られているキーワードを使うことができるという利点があります。 は、型の別名を導入します。しかし、この方法にはいくつかの デメリットは、特に、「negative」キーワードを使用することによる混乱です。 型名の別名を導入するコンテキストで、その別名が型名でない場合 は、型を指定するのではなく、テンプレートを指定します。
Vec
のエイリアスではありません。 型と同じであり,型定義名と同じとみなしてはならない。型名Vec
は 家名std::vector< [bullet] , MyAllocator< [bullet] > >
- ここで、箇条書きはタイプ名のプレースホルダーである。その結果、私たちは typedef」構文は提案しない。一方,文template<class T> using Vec = std::vector<T, MyAllocator<T> >;
は、次のように読み解くことができます。
Vec<T>
として の同義語です。std::vector<T, MyAllocator<T> >
. このように読むと エイリアシングの新しい構文は、合理的だと思います。
重要なのは、ここでの区別だと思います。 エイリアス の代わりに タイプ s. もう一つ、同じ文書から引用します。
<ブロッククオートalias-declarationは宣言であり、定義ではありません。エイリアス 宣言は、ある名前をエイリアスとして宣言的な領域に導入します。 は、宣言の右辺で指定された型のために使用されます。この この提案の核心は、型名エイリアスに関するものですが の表記を一般化して、別の綴りを提供することができます。 の名前空間エリシングやオーバーロードされた関数の名前付け(✁を参照)。 2.3で詳しく説明します)。[ 注:このセクションでは、その構文がどのように見えるか、そしてそれが提案の一部でない理由を論じています。 ] 文法プロダクション alias-declaration は、typedef 宣言や名前空間別名定義が許容されます。
まとめ:役割としては
using
:
- テンプレートのエイリアス (またはテンプレートの型定義、名前的には前者が好ましい)
-
名前空間エイリアス(つまり。
namespace PO = boost::program_options
とusing PO = ...
に相当) -
という文書があります。
A typedef declaration can be viewed as a special case of non-template alias-declaration
. 美的な変化であり、この場合は同一と見なします。 -
スコープに入れる(例.
namespace std
グローバルスコープへ)、メンバ関数、コンストラクタの継承
それは できない に使える。
int i;
using r = i; // compile-error
そのかわり、こうしてください。
using r = decltype(i);
オーバーロードの集合に名前を付ける。
// bring cos into scope
using std::cos;
// invalid syntax
using std::cos(double);
// not allowed, instead use Bjarne Stroustrup function pointer alias example
using test = std::cos(double);
関連
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] ムーブセマンティクスとは何ですか?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】C++11のラムダ式って何?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み] C++11のランダムライブラリを使って乱数を生成する
-
[解決済み】C++テンプレートのtypedef