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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

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

    View full-size 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 full-size 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 full-size 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 full-size slide

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










    View full-size slide

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
















    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

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

    View full-size slide