どうも、
忍者ブログの不便さに辟易としてきたまむです!
今回は、そろそろC++を本格的に扱いだしたのではないかと思われる、二年生の方向けの記事を書きます。
今回の題材は「using」です。
[1回]
usingは、いくつかの役割を持っています。
まず最初に、有名な「namespaceの省略」から。
#include <iostream>
using namespace std;
int main() {
cout << "Hello, world!" << endl;
return 0;
}
実行結果「cout」や「endl」の頭に付けていた煩わしいstdを滅ぼすことができました。
しかし、安易にusing namespaceを使用すると大変危険です。
以下のコードを見てみましょう。
#include <string>
using namespace std;
typedef char* string;
int main() {
string name = "Alice";
return 0;
}
実行結果「std名前空間」には「string」という型が存在しています。
「std名前空間にあるstring」では長いので「std::string」と書くことにしましょう。
……そういえばusing namespace stdを使用しているので「std」は省けますね。じゃあ「string」と書きましょうか。
さて、名前空間のない所で「char*のエイリアス(別名)string」を定義しましょう。
これもまた「名前空間のない所にあるchar*のエイリアスstring」では長いので「string」と書くことにしましょう。
さて、この時点でどこがまずいのか分かりますね。
そう、「string」という名前が思いっきり被ってしまっているのです。
こういった現象を「名前の衝突」と呼びます。
namespaceは、名前の衝突を避ける為に必要なものなので、安易にusing namespaceを使用して省略しないでね、というお話でした。
usingのネガキャンみたいになってしまいましたが、今回の記事タイトルは「usingのススメ」です。
最初に「いくつかの役割を持っている」と記した通り、usingの使用方法はこれだけではありません。
次のコードを見てみましょう。
using string = const char *;
using wstring = const wchar_t *;
int main() {
string name = "Alice";
wstring wname = L"アリス";
return 0;
}
実行結果今回の役割は「typedefの代替」です。
typedefでは、型名のエイリアスを定義できましたが、usingを使用しても同じことができます。
「ならtypedefでいいじゃん」との声が聞こえてきそうですが、usingを利用する一番の利点は、その記述方法にあります。
関数ポインタfunction(int, int)のエイリアス定義の例を見てみましょう。
typedef int (*Function)(int, int);
using Function = int (*)(int, int);
どちらも記法が違うだけですが、usingの方が「エイリアスとして定義している」ことや「どこまでが型名でどこまでがエイリアスなのか」が分かりやすく、可読性が高まるかと思われます。
また、usingとtypedefの決定的な違いは「templateが使用できる」という点です。
template<typename T>
typedef std::vector<T> Vec;
このコードはコンパイルが通りませんが、
template<typename T>
using Vec = std::vector<T>;
usingを使用した場合、コンパイルが通ります。
これを活用することで、二つ以上の型パラメータを求められるとき片方を固定するなど、様々なことができるようになります。
最後に、以下のコードをご覧ください。
#include <iostream>
namespace Hoge {
void f() { std::cout << "Hoge::f()" << std::endl; }
}
void f() { std::cout << "::f()" << std::endl; }
int main() {
using Hoge::f;
f();
return 0;
}
実行結果これは、using namespaceと非常に似た使用方法です。
しかし、大きく違うのは「宣言済みである指定の名前のものを持ってきて、現在のスコープに取り込む、或いは同名のものを覆い隠す」という動作を行うことです。
指定した物だけを持ってくることができるので、名前の衝突が起こる可能性が低くなります。
活用方法はあんまり思いつきませんが、覚えておいて損はしないでしょう。
長々と書いてきましたが、私が伝えたいことは「typedefよりusingを使おう」ということだけです。
ここまで読んで下さり、ありがとうございました!
はてな記法使いたい。PR
COMMENT