Upgrade to Pro — share decks privately, control downloads, hide ads and more …

みんな大好き!using ディレクティブ! / using directive

みんな大好き!using ディレクティブ! / using directive

C++MIX #7 の発表資料です。

Miutsuru kariya

January 29, 2020
Tweet

More Decks by Miutsuru kariya

Other Decks in Programming

Transcript

  1. みんな大好き!
    using ディレクティブ!
    2020/1/29 鳥頭かりやマン
    1

    View Slide

  2. 初心者向けネタ発表です。
    「そんなんみんな知っとるが」など、その
    筋の方からのツッコミは無しの方向でお
    願いします…
    2

    View Slide

  3. using ディレクティブとは?
    3

    View Slide

  4. using ディレクティブとは?
    雑な説明
    指定した名前空間のメンバを
    名前空間名の修飾無しで
    使えるようになる。
    4

    View Slide

  5. using ディレクティブの
    使い方
    5

    View Slide

  6. using ディレクティブの使い方
    #include
    namespace N {
    void hell() {
    std::cout << "Hell, World!" << std::endl;
    }
    }
    int main()
    {
    N::hell();
    }
    6

    View Slide

  7. using ディレクティブの使い方
    #include
    namespace N {
    void hell() {
    std::cout << "Hell, World!" << std::endl;
    }
    }
    int main()
    {
    N::hell();
    }
    std::が鬱陶しい!
    ※ いや、個人的には std::endl は基本使わないんですが、気にしない方向で…
    7

    View Slide

  8. using ディレクティブの使い方
    そこで
    using ディレクティブ
    ですよ奥さん!
    8

    View Slide

  9. using ディレクティブの使い方
    using
    namespace
    std
    読み人知らず
    9

    View Slide

  10. using ディレクティブの使い方
    #include
    using namespace std;
    namespace N {
    void hell() {
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    スッキリした!
    素晴らしい!
    10
    using ディレクティブ入れてみた

    View Slide

  11. 余談:using 何て?
    いつもの C++ の予約語使いまわし芸のせい
    で、予約語 using を使った構文は他にもいっ
    ぱいあるので、ご注意を!
    using-declaration
    using-enum-declaration※
    alias-declaration
    attribute-using-prefix
    ※ NEW!!! C++20!!! 11

    View Slide

  12. みんな大好き!
    using ディレクティブ
    12

    View Slide

  13. みんな大好き!
    using ディレクティブ
    13
    これじゃ
    あんまりなので…

    View Slide

  14. using ディレクティブの使い方
    せっかく名前衝突を
    避けるために名前空間作った
    のに、グローバル名前空間で
    やっちゃうのは
    どうなの???
    14

    View Slide

  15. using ディレクティブの使い方
    #include
    namespace N {
    using namespace std;
    void hell() {
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    15
    名前空間Nに
    using ディレクティブ入れてみた

    View Slide

  16. 名前空間Nに
    using ディレクティブ入れてみた
    using ディレクティブの使い方
    #include
    namespace N {
    using namespace std;
    void hell() {
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    これならNの外には影響なし!
    素晴らしい!
    16

    View Slide

  17. using ディレクティブのワナ
    17

    View Slide

  18. using ディレクティブのワナ
    #include
    namespace N {
    using namespace std;
    auto cout = 42;
    void hell() {
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    18
    ちょっと名前が被っただけで…
    ※ そんな変な名前使わねぇよ、と言うツッコミは無しの方向で…
    (実際std名前空間にはめっさ名前があるから許して…)

    View Slide

  19. using ディレクティブのワナ
    #include
    namespace N {
    using namespace std;
    auto cout = 42;
    void hell() {
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    19
    コンパイルエラー!
    そりゃそうだ…
    ※ そんな変な名前使わねぇよ、と言うツッコミは無しの方向で…
    (実際std名前空間にはめっさ名前があるから許して…)
    ちょっと名前が被っただけで…

    View Slide

  20. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    20
    using ディレクティブは名前空間スコー
    プだけじゃなくて、ローカルスコープ
    でも使えます!!!1!

    View Slide

  21. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    21
    using ディレクティブは名前空間スコー
    プだけじゃなくて、ローカルスコープ
    でも使えます!!!1!
    やっぱり
    コンパイルエラー!

    View Slide

  22. using ディレクティブは名前空間スコー
    プだけじゃなくて、ローカルスコープ
    でも使えます!!!1!
    using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    22
    やっぱり
    コンパイルエラー!
    何で!?

    View Slide

  23. using ディレクティブのワナ
    もう一度
    ソースを
    よ~く見てみる…
    23

    View Slide

  24. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    24
    自分で定義したcoutは
    名前空間スコープにある…

    View Slide

  25. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    25
    自分で定義したcoutは
    名前空間スコープにある…
    std::coutは当然std名前空間にあるけど、
    usingディレクティブでローカルスコープに
    持ってきたんだから、名前空間Nよりも内側
    にあるのでcoutで使えるんじゃ…

    View Slide

  26. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    26
    自分で定義したcoutは
    名前空間スコープにある…
    std::coutは当然std名前空間にあるけど、
    usingディレクティブでローカルスコープに
    持ってきたんだから、名前空間Nよりも内側
    にあるのでcoutで使えるんじゃ…
    ナゾ!

    View Slide

  27. using ディレクティブのワナ
    困ったら
    エゾえもんに
    相談だ!
    27










    View Slide

  28. using ディレクティブのワナ
    困ったら
    エゾえもんに
    相談だ!
    28
















    View Slide

  29. using ディレクティブのワナ
    困ったら
    原典(規格書)に
    あたってみよう!
    http://eel.is/c++draft マジで神!
    29

    View Slide

  30. using ディレクティブのワナ
    9.8.3 Using namespace directive [namespace.udir]
    2. During unqualified name lookup, the names
    appear as if they were declared in the nearest
    enclosing namespace which contains both the using-
    directive and the nominated namespace.
    http://eel.is/c++draft/namespace.udir#2
    30

    View Slide

  31. using ディレクティブのワナ
    9.8.3 Using namespace directive [namespace.udir]
    2. During unqualified name lookup, the names
    appear as if they were declared in the nearest
    enclosing namespace which contains both the using-
    directive and the nominated namespace.
    http://eel.is/c++draft/namespace.udir#2
    31
    英語
    読めん!

    View Slide

  32. ぐ~ぐるコンニャク~!
    using ディレクティブのワナ
    32

    View Slide

  33. using ディレクティブのワナ
    9.8.3名前空間ディレクティブの使用
    [namespace.udir]
    2.修飾されていない名前のルックアップ中、名前は、
    usingディレクティブと指定されたネームスペースの
    両方を含む最も近い囲みネームスペースで宣言さ
    れているように表示されます。
    http://eel.is/c++draft/namespace.udir#2
    ちと微妙だけどまぁ雰囲気は分かるかな…
    33

    View Slide

  34. using ディレクティブのワナ
    もう一度
    ソースを
    よ~く見てみる…
    34

    View Slide

  35. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    35
    このusingディレクティブを囲む
    名前空間はN。

    View Slide

  36. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    36
    このusingディレクティブを囲む
    名前空間はN。
    このusingディレクティブで指定
    された名前空間はstd。

    View Slide

  37. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    37
    Nとstdの両方を囲む最も近い名前
    空間は、グローバル名前空間。
    このusingディレクティブを囲む
    名前空間はN。
    このusingディレクティブで指定
    された名前空間はstd。

    View Slide

  38. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    38
    つまり、std::coutはグローバル
    名前空間にあるように見える。
    一方、自分で定義したcout変数は
    名前空間Nにある。

    View Slide

  39. using ディレクティブのワナ
    #include
    namespace N {
    auto cout = 42;
    void hell() {
    using namespace std;
    cout << "Hell, World!" << endl;
    }
    }
    int main()
    {
    N::hell();
    }
    39
    この場合
    std::coutは
    単純名では
    見えない!!!

    View Slide

  40. using ディレクティブのワナ
    #include
    namespace A {
    auto s = "ほげ";
    }
    namespace B {
    auto s = "はげ";
    void f() {
    using namespace A;
    std::cout << s << std::endl;
    }
    }
    int main()
    {
    B::f();
    }
    40
    この s は "ほげ" じゃなくて "はげ"!

    View Slide

  41. 結論
    41

    View Slide

  42. 結論
    using ディレクティブは用法用量
    を守って正しくお使いください
    他のワナとしてusingディレクティブは推移的ってのもあるので(usingディレクティブで指定
    した名前空間にusingディレクティブがあると、連鎖的にそいつの影響も受ける)、個人的に
    は使わないことをお勧めします。
    using-declarationやnamespace-alias-definitionならもうちょっと挙動が素直なので…
    42

    View Slide