概要

usingには、using宣言 (using declaration)、および、using指令 (using directive) の2つがある。

これらは異なる用途で使用される。

  • using宣言
    特定の名前をスコープに導入する際に使用する。
    例えば、using std::cout;のように記述し、特定の要素のみを現在のスコープで使用可能にする。

  • using指令
    名前空間全体をスコープに導入する際に使用する。
    例えば、using namespace std;のように記述し、指定した名前空間内の全ての要素を現在のスコープで使用可能にする。


これらの機能は、ソースコードの可読性と保守性の向上に寄与する。

また、型指定が可能なstd::vectorやstd::map等のテンプレートクラスも個別に宣言することができる。

ちなみに、usingディレクティブを用いてusing namespace std;と記述すれば、std名前空間の全てのメンバの省略記法が一括で利用可能になるが、
若干危険であるため (参考 : usingディレクティブ|using namespace std; の危険性と注意点・代替案)、個別に宣言する方法を推奨する。


using宣言

using宣言(using declaration)によって、特定のメンバのみを取り込むことができる。
クラススコープ以外の一般的なスコープで宣言が可能である。

 using std::cout;
 using std::endl;
 
 // 以前の記述方法
 std::cout << 123 << std::endl;
 
 // 新しい記述方法
 cout << 123 << endl;


関数の場合も同じ記法を用いる。

 using std::max;
 using std::sort;
 using std::move;


std::stringクラスの場合も変数の時と同様の記法が使用できる。

 using std::string;
 
 string strhoge = "abcde";



エイリアス宣言

std::vector<std::string>等のテンプレートクラスの場合には、エイリアス宣言(alias declaration)による別名での宣言が必要となる。

 using String  = std::string;
 using strings = std::vector<std::string>;
 
 strings strvec = {"A", String("B")};



エイリアステンプレート

エイリアステンプレート(alias templates)により、型指定が必要なテンプレートクラス(std::array<T>やunique_ptr<T>等)を別名で定義することもできる。

 template<typename T>
 using vector = std::vector<T>;
 
 vector<int> v = {1, 2, 3};



usingの活用方法

これらのusing宣言 / エイリアス宣言 / エイリアステンプレートによる個別の宣言と定義をどのタイミングで行うべきか、
using namespace std;の代替として使用するのであれば、ファイルスコープへの汚染を慎重に考慮した上で、
従来通り、main関数の外や実装ファイルの冒頭で利用するのもよい。

ただし、最も推奨するのは、必要になった時に局所的に定義する方法である。頻繁に使用しないクラスではこちらの方法がベストである。

 namespace mylib
 {
    // 名前空間で個別に宣言(mylib内限定で利用可能)
    using std::cout;
 
    void test()
    {
       // 関数内で個別に宣言
       using std::endl;
 
       cout << 1 << endl;
       cout << 2 << endl;
    }
 
    struct String
    {
       // クラス内で個別に定義
       using string = std::string;
 
       string _str;
       String(const char* str) : _str(str) {}
       void print() { cout << _str << std::endl; }
    };
 
    // 下記に示す無名の名前空間の場合、同一の名前空間に汚染するので注意する
    namespace { using std::endl; }
    // 侵食したendlが使えてしまう
    void hazard() { std::cout << endl; }
 }