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

みんな代替トークン使とる。使てへんのお前だけ。 / alternative tokens

みんな代替トークン使とる。使てへんのお前だけ。 / alternative tokens

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

Miutsuru kariya

January 29, 2020
Tweet

More Decks by Miutsuru kariya

Other Decks in Programming

Transcript

  1. みんな代替トークン使とる。
    使てへんのお前だけ。
    2020/1/29 鳥頭かりやマン
    1

    View Slide

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

    View Slide

  3. 代替トークンとは?
    3

    View Slide

  4. 代替トークンとは?
    「代替」の「トークン」
    まんま…
    なお、よく「ダイグラフ」と
    呼ばれたりもするが…
    4

    View Slide

  5. 代替トークンとは?
    代替 本来 代替 本来 代替 本来
    <% { and && xor ^
    %> } bitand & xor_eq ^=
    <: [ and_eq &= not !
    :> ] or || not_eq !=
    %: # bitor | compl ~
    %:%: ## or_eq |=
    5
    見ての通り、必ずしも「ダイ」(2文字)ではなく、
    キーワード型の物も結構ある。
    これらの名前も予約語なので、例えば and や
    or と言った関数名や変数名は使えない。




















    View Slide

  6. 代替トークンとは?
    代替 本来 代替 本来 代替 本来
    <% { and && xor ^
    %> } bitand & xor_eq ^=
    <: [ and_eq &= not !
    :> ] or || not_eq !=
    %: # bitor | compl ~
    %:%: ## or_eq |=
    6
    なお、「トークン」と名前がついている通り、コンパイラが
    ソースをトークン化する際に処理されるので、文字列中
    や他の識別子中では代替トークンとはみなされない。
    まぁ当たり前っちゃあ当たり前なんだけど…

    View Slide

  7. 使用例
    7

    View Slide

  8. 使用例
    使用前
    #include
    int main()
    {
    int a[] = { 114, 514, };
    for (int i = 0; i < 2; ++i) {
    std::cout << a[i] << ", ";
    }
    std::cout << '\n';
    }
    8

    View Slide

  9. 使用例
    使用後
    %:include
    int main()
    <%
    int a<::> = <% 114, 514, %>;
    for (int i = 0; i < 2; ++i) <%
    std::cout << a<:i:> << ", ";
    %>
    std::cout << '\n';
    %>
    9

    View Slide

  10. 使用例
    使用後
    %:include
    int main()
    <%
    int a<::> = <% 114, 514, %>;
    for (int i = 0; i < 2; ++i) <%
    std::cout << a<:i:> << ", ";
    %>
    std::cout << '\n';
    %>
    10
    読みやすい!
    (異論は認める)

    View Slide

  11. 使用例
    …これ、使う気がしない…
    11

    View Slide

  12. 使用例
    …これ、使う気がしない…
    と思いましたね?
    12

    View Slide

  13. 使用例
    使用前
    template
    bool
    all_of(InputIterator first, InputIterator last, Predicate pred)
    {
    for (; first != last; ++first)
    if (!pred(*first))
    return false;
    return true;
    }
    13
    否定演算子が
    見づらい!

    View Slide

  14. 使用例
    使用後
    template
    bool
    all_of(InputIterator first, InputIterator last, Predicate pred)
    {
    for (; first != last; ++first)
    if (not pred(*first))
    return false;
    return true;
    }
    14
    否定演算子が
    見やすい!
    (異論は認めない)

    View Slide

  15. 使用例
    どうですか?
    使いたくなってきませんか?
    15

    View Slide

  16. ビット反転演算子が
    見づらい!
    使用例
    使用前
    const result_type Yp = (x[i] & ~mask) |
    (x[j] & mask);
    const size_t k = (i + m) % n;
    x[i] = x[k] ^ rshift<1>(Yp) ^ (a * (Yp & 1));
    result_type z = x[i] ^ (rshift(x[i]) & d);
    i = j;
    z ^= lshift(z) & b;
    z ^= lshift(z) & c;
    return z ^ rshift(z);
    16

    View Slide

  17. ビット反転演算子が
    見やすい!
    (異論は認める)
    使用例
    使用後
    const result_type Yp = (x[i] & compl mask) |
    (x[j] & mask);
    const size_t k = (i + m) % n;
    x[i] = x[k] ^ rshift<1>(Yp) ^ (a * (Yp & 1));
    result_type z = x[i] ^ (rshift(x[i]) & d);
    i = j;
    z ^= lshift(z) & b;
    z ^= lshift(z) & c;
    return z ^ rshift(z);
    17

    View Slide

  18. 使用例
    使用後(過激派)
    const result_type Yp = (x<:i:> bitand compl mask) bitor
    (x<:j:> bitand mask);
    const size_t k = (i + m) % n;
    X<:i:> = x<:k:> xor rshift<1>(Yp) xor (a * (Yp bitand 1));
    result_type z = x<:i:> xor (rshift(x<:i:>) bitand d);
    i = j;
    z xor_eq lshift(z) bitand b;
    z xor_eq lshift(z) bitand c;
    return z xor rshift(z);
    18

    View Slide

  19. 何もかもが
    見やすい!
    (異論は認める)
    使用例
    使用後(過激派)
    const result_type Yp = (x<:i:> bitand compl mask) bitor
    (x<:j:> bitand mask);
    const size_t k = (i + m) % n;
    X<:i:> = x<:k:> xor rshift<1>(Yp) xor (a * (Yp bitand 1));
    result_type z = x<:i:> xor (rshift(x<:i:>) bitand d);
    i = j;
    z xor_eq lshift(z) bitand b;
    z xor_eq lshift(z) bitand c;
    return z xor rshift(z);
    19

    View Slide

  20. 使用例
    使用前
    template class BinaryPredicate>
    pair
    mismatch(InputIterator1 first1, InputIterator1 last1,
    InputIterator2 first2, InputIterator2 last2,
    BinaryPredicate pred)
    {
    for (; first1 != last1 && first2 != last2; ++first1, ++first2)
    if (!pred(*first1, *first2))
    break;
    return pair(first1, first2);
    }
    20

    View Slide

  21. 使用例
    使用後
    template class BinaryPredicate>
    pair
    mismatch(InputIterator1 first1, InputIterator1 last1,
    InputIterator2 first2, InputIterator2 last2,
    BinaryPredicate pred)
    {
    for (; first1 != last1 and first2 != last2; ++first1, ++first2)
    if (not pred(*first1, *first2))
    break;
    return pair(first1, first2);
    }
    21

    View Slide

  22. 使用例
    ところで皆さん、
    代替トークンの字面に
    惑わされてはいませんか?
    22

    View Slide

  23. 使用例
    使用前
    struct S {
    S() = default;
    S(const S&) = default;
    S(S&&) = default;
    ~S() = default;
    };
    23
    まっ、まさか…

    View Slide

  24. 使用例
    使用後
    struct S <%
    S() = default;
    S(const S bitand) = default;
    S(S and) = default;
    compl S() = default;
    %>;
    24
    まっ、まさか…
    そのまさかだ、フハ
    ハハハハハハハ!

    View Slide

  25. 使用例
    使用後
    struct S <%
    S() = default;
    S(const S bitand) = default;
    S(S and) = default;
    compl S() = default;
    %>;
    25
    まっ、まさか…
    そのまさかだ、フハ
    ハハハハハハハ!
    スゴい!
    参照もデストラクタも
    見やすい!

    View Slide

  26. まっ、まさか…
    そのまさかだ、フハ
    ハハハハハハハ!
    使用例
    使用後
    struct S <%
    S() = default;
    S(const S bitand) = default;
    S(S and) = default;
    compl S() = default;
    %>;
    26
    スゴい!
    参照もデストラクタも
    見やすい!
    ダメ!ゼッタイ!

    View Slide

  27. 結論
    27

    View Slide

  28. 結論
    代替トークン普及の会からのお知らせ
    みんな積極的に
    代替トークンを使おう!
    せめて忘れないであげてください!!!
    28

    View Slide

  29. 蛇足①
    ちなみに、C++17で廃止されてしまったトライグラフは、トー
    クン化どころかプリプロセス前に処理されていたので、文字
    列内とかでも問答無用で変換対象になっていた。
    29
    代替 本来 代替 本来 代替 本来
    ??= # ??( [ ??< {
    ??/ \ ??) ] ??> }
    ??’ ^ ??! | ??- ~

    View Slide

  30. 蛇足①
    使用前(再掲)
    #include
    int main()
    {
    int a[] = { 114, 514, };
    for (int i = 0; i < 2; ++i) {
    std::cout << a[i] << ", ";
    }
    std::cout << '\n';
    }
    30

    View Slide

  31. 蛇足①
    使用後(トライグラフ)
    ??=include
    int main()
    ??<
    int a??(??) = ??< 114, 514, ??>;
    for (int i = 0; i < 2; ++i) ??<
    std::cout << a??(i??) << ", ";
    ??>
    std::cout << '\n';
    ??>
    31

    View Slide

  32. 蛇足①
    使用後(トライグラフ)
    ??=include
    int main()
    ??<
    int a??(??) = ??< 114, 514, ??>;
    for (int i = 0; i < 2; ++i) ??<
    std::cout << a??(i??) << ", ";
    ??>
    std::cout << '\n';
    ??>
    実際某青いI社のメインフレームで見たときは正直キモかった…(個人の感想です)
    32
    読みづらい!
    (異論は認める)

    View Slide

  33. 蛇足➁
    C++のトークン化は、通常最長のトークンを切り出すことに
    なっている。
    例)
    external
    ⇒ “extern”と“al”と言う2つのトークンではなく、 “external”と言う単一のトークン
    a+++++b
    ⇒ “a” “++” “+” “++” “b” ではなく、“a” “++” “++” “+” “b” と言うトークン列
    33

    View Slide

  34. 蛇足➁
    しかし、代替トークンに関連した以下のような例外がある。
    “<::”の後ろに続く文字が“>”でも“:”でもなかった場合、
    “<”と“::”と言う2つのトークンになる。
    “<:” ⇒ “{”
    “<::” ⇒ “<” と “::”
    “<::>” ⇒ “{” と “}”
    “<:::” ⇒ “{” と “::”
    まぁ普通この規則に引っかかることはおそらく一生のうち1度も無いとは思う…
    34

    View Slide

  35. 蛇足➂
    C言語では、キーワード型の代替トークンは言語仕様ではな
    く、ヘッダで提供されている。
    35
    代替 本来 代替 本来 代替 本来
    <% { and && xor ^
    %> } bitand & xor_eq ^=
    <: [ and_eq &= not !
    :> ] or || not_eq !=
    %: # bitor | compl ~
    %:%: ## or_eq |=
    言語仕様で提供 ヘッダiso646.hで提供

    View Slide

  36. みんな代替トークン使とる。
    使てへんのお前だけ。
    36


    制作・著作
    ━━━━━
    ⓃⒽⓀ

    View Slide