HHK / RealForce / Majestouch MINILA くらべ

私の職場では私は表題に掲げた3種のキーボードを使うことができるという幸運に恵まれています。

いずれも英語(US)配列のキーボードです。

せっかくなので、ここ数カ月間使ってみた感想等を書いてみます。
評価基準が偏ってるのであまり参考にならないかもしれませんが。

キーの配列については、以下の配列を標準と見なして、そこからの差分などについて言及します。

HHK


  • 雑感
      前職のときから使っていたので最も手に馴染んでいます。なので、この評価にはある程度バイアスがかかっていると思います。そこも含めて参考になさってください。
      無刻印モデルはさすがに手を出せなかったので薄墨モデルを使用しています。(たまに Print Screen キーを押したくなったりしたときに無刻印だと詰む)
      コンパクトさのためにキー配列がかなり特殊なので、慣れるのに時間を要するかもしれません。
      また、いったんこのキーボードに慣れてしまうと他のキーボードを触るのが苦痛になるかもしれません。


  • Good(個人的に 良い と感じる点)

    • ◇キー
      ちゃんと独自のスキャンコードを生成するため、Xmodmap とか AutoHotKey とかで使いやすい → 個人的に最大の評価ポイント
      例えばカーソルキーが無い代わりに ◇ + h, j, k, l で上下左右のキーコードを生成するように Xmodmap や AutoHotKey を設定することが容易になります。◇ キーをうまく使いこなせば、親指シフト的な、ホームポジションから手を動かさずにできることの幅がぐっと広がります。

    • 打鍵感
      個人的には一番好みです。軽すぎず重すぎないと感じます。

    • 打鍵音は静かなほうだと思います。


  • Bad

    • 標準の US 配列とかけ離れた位置にキーが配置されているものがあります。(~ など)

    • Windows キーが存在しません → Windows で使わなければ特に支障はありません

    • ほかにも存在しないキーや Fn との組み合わせでしか入力できないキーがたくさんあります。(とくに独立したカーソルキーが存在しないことが普通の方々には致命的かもしれません。emacs や vi のキーバインドで生きている人向けのキーボードでしょう)


  • キー配置の特徴(標準配列との違い)

    • デフォルトでは Backspace キーは存在せず、Delete キーになっています。ディップスイッチにより Delete キーを Backspace キーに切り替え可能です。このあとはディップスイッチによって Delete キーを Backspace キーに切り替えた前提で書きます。

    • Backspace キーは Enter キーの直上にあります。標準では \(バックスラッシュ) |(パイプ) キーがある位置です。\| キーはさらにその上(一番上の段)にあります。標準では Backspace キーになっているキーが左右2つに分割されて、その左側のキーが \| キーに、右側のキーが `(バッククオート) ~(チルダ)キーになっています。

    • Esc キーは 1 の左、Tab キーの上にあります。標準では `~ キーがある位置です。

    • Caps Lock キーは Fn キー + Tab です。

    • 左 Control キーは標準 Caps Lock キーの位置にあります。標準では左 Control キーがある位置(キーボードの一番左下)には、物理的にキーが存在しません。

    • 標準では Super キーが存在する位置に、Alt キーがあります。(左右とも)

    • 標準では Alt キーが存在する位置に、◇ キーがあります。(左右とも)

    • Meta キーおよび右 Control キーは存在しません。

    • 上下左右のカーソルキーは存在しません。Fn キーとの組み合わせで実現します。

    • F1〜F12 キーは存在しません。Fn キーとの組み合わせで実現します。

    • Ins、Home、Page Up などのキーも存在しません。Fn キーとの組み合わせで実現します。


  • その他

    • USB ハブのように使えるポートを 2 ポート持っています

    • PC 本体と接続する USB ケーブルは着脱可能です。キーボード側のコネクタは USB mini B です。




Majestouch Minila

Majestouch MINILA US67キー 茶軸 FFKB67M/EB

Majestouch MINILA US67キー 茶軸 FFKB67M/EB


  • Good

    • ディップスイッチで交換できるキーのために、交換用キートップがついてきます。
      例)CapsLock キーを Ctrl に変更する人のために、CapsLock と同じ大きさの Ctrl キーのキートップが付属している。
      ディップスイッチでキー配置を変えたとしても大丈夫!

    • キートップ交換用の治具(キートップを引き抜くための道具)がついてくる
      地味に便利


  • Bad

    • 打鍵感が軽めです。HHKRealforce を使ったあとだと、手応え不足を感じます。(茶軸だからかもしれません)

    • 打鍵音が大きめです。軽いカチャカチャという音がします。(茶軸だからかもしれません。)

    • 親指 Fn キーがスキャンコードを発生しないので Xmodmap とか AutoHotKey で使えません。FILCO お仕着せのキーバインドのためにしか使えません。
      非常にもったいない。このキーボードの最大のマイナスポイントです。


  • キー配置の特徴

    • Esc キーの位置が特殊です。標準配列では `~ キーになっている場所に Esc キーがあります。Fn + Esc で `~ キーになります。また、ディップスイッチにより ESC キーを恒常的に`~ キーに変えることが可能です。その際 Esc キーは Fn + ` にります。

    • `~ は Fn との組み合わせで実現するだけでなく、普通のキーとしても配置されています。最上段の右から 2 番目にあります。標準配列では Backspace になっている横長のキーが左右に分割されて、その左側のキーが `~ キーになっています。(右側は Backspace です)

    • Enter キーの上は標準配列どおり \| キーになっています。

    • Backspace と \| キーは、ディップスイッチにより入れ替えが可能です。

    • 私は AutoHotKey で `~ キーを \| キーと入れ替えて HHK っぽくして使っています。

    • 左 Super キーは Windows キー、右 Super キーは App キーになっています。Meta キーに相当するキーはないようです。

    • キーボード右下に無理やりカーソルキーを押し込んだような配置のため、カーソルキーはあまり押しやすくはないです。右 Shift キーと Delete キーも申し訳程度についてますが、キーを見ないで押すことが(いまだに)できません。


  • その他

    • USB ハブのように使えるポートを 1 ポート持っています。

    • PC 本体と接続する USB ケーブルは着脱可能です。キーボード側のコネクタは USB mini B です。




RealForce

東プレ REALFORCE 86U /静電容量無接点/変荷重/86キー/USB SE0500

東プレ REALFORCE 86U /静電容量無接点/変荷重/86キー/USB SE0500


  • Good

    • 標準配列に忠実なキー配置です。標準との違いは、最初から左 Control キーと Caps Lock キーが入れ替わっていることと、Meta キーに相当するキーが存在しないことくらいでしょうか。3 つの中では最も素直で万人に受け入れられやすいキー配置ではないでしょうか。

    • 打鍵音は静かなほうです。HHK との違いはほとんど感じません。


  • Bad

    • 打鍵感が重めです。ずっと打っていると疲れます。私の力加減がよくないのかもしれません。(私はしっかりと最後まで押しこみたいタイプです)

    • 他の 2 製品と比べて、Esc キーが遠く感じます。vi 使いにはツラいところです。

    • USB ケーブルがキーボード本体に直結されているので、必要な長さにあわせてケーブルを取り替えたりすることができません。長くしたい分には延長することも可能かもしれませんが、短くすることができません。キーボードのケーブルは意外と机の上で邪魔になるものです。

    • それほど重大な問題ではありませんが、USB ハブとしての機能はありません

    • 設置面積は 3 製品中最大です。F1〜F12 キーや Ins/Home/Page Up などのキー、カーソルキーが余裕を持って配置されているためだと思います。逆にその余裕のおかげでそれらのキーもブラインドタッチできますので、メリットと感じる人もいるかもしれません。

  • キー配置の特徴

    • Good のところで書いた2点以外にキー配置上の特徴らしい特徴はありません。逆にそのことが特徴なのかもしれません。



まとめ

やっぱり個人的には HHK がベストかな、という結論に落ち着きました。
単に、より使い慣れているというだけのような気もしますが、キー配置のカスタマイズ時に◇キーが使えるのが大きいですね。

git svn でローカルでは commit したけどまだ dcommit してないコミットがあるかどうかをコマンドラインで調べる方法

人間が目で見て把握するには gitk などの GUI ツールでもあれば十分なのですが、機械にそれを調べさせるにはコマンドで実行したいところです。

調べたところ、以下のワンライナーで十分なようです。

$ git log remotes/git-svn.. --oneline

GotW #2: Temporary Objects 一時オブジェクト(勝手訳)

第2回めの GotW の翻訳です。

例によって原文著者(Herb Sutter 氏)の許可は得ていませんし、私の英訳がヒドいクオリティである(用語の統一がとれていないとか、誤訳が含まれているとか)かもしれませんのでそこのところはご理解いただければと思います。


原文:http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/


Unnecessary and/or temporary objects are frequent culprits that can throw all your hard work—and your program’s performance—right out the window. How can you spot them and avoid them?

必要がなかったり一時的にしか使われない(もしくはその両方であるような)オブジェクトは、あなたの大変な努力を - そしてあなたのプログラムのパフォーマンスを - 台無しにすることがあります。

Problem 問題

JG Question 見習いグルへの質問


1. What is a temporary object?

1. 一時オブジェクトとは何か?

Guru Question グルへの質問


2. You are doing a code review. A programmer has written the following function, which uses unnecessary temporary or extra objects in at least three places. How many can you identify, and how should the programmer fix them?

2. あなたはコードレビューを行なっている。あるプログラマが以下のような関数を書いた。その中では不必要な一時オブジェクトや余分なオブジェクトが少なくとも3箇所で使われている。あなたはいくつ見つけられるか?そしてそのプログラマはどのようにそれを直すべきか?

string find_addr( list<employee> emps, string name ) {
    for( auto i = begin(emps); i != end(emps); i++ ) {
        if( *i == name ) {
            return i->addr;
        }
    }
    return "";
}


Do not change the operational semantics of this function, even though they could be improved.

この関数の動作上のセマンティクスを変更してはならない。たとえそれが改善につながるとしても。

Solution 解

1. What is a temporary object?

1. 一時オブジェクトとは何か?

Informally, a temporary object is an unnamed object that you can’t take the address of. A temporary is often created as an intermediate value during the evaluation of an expression, such as an object created by returning a value from a function, performing an implicit conversion, or throwing an exception. We usually call a temporary object an “rvalue,” so named because it can appear on the “r”ight hand side of an assignment. Here are some simple examples:

正式な言い方ではありませんが、一時オブジェクトとはそのアドレスを取得することができない無名オブジェクトです。一時オブジェクトはしばしば、関数からのリターン、暗黙の変換の実行もしくは例外のスローによって生成されるオブジェクトのような、式の評価の間の中間的な値として生成されます。私たちは通常、一時オブジェクトのことを rvalue と呼びます。代入文の右辺("r"ight hand side)に現れるものだからです。いくつかのシンプルな例をお見せします:

widget f();            // f は 一時的な widget オブジェクトを返す

auto a = 0, b = 1;
auto c = a + b;        // "a+b" は一時的な int オブジェクトを生成する

In contrast, in the same code we have objects like a and c that do each have a name and a memory address. Such an object is usually called an “lvalue,” because it can appear on the “l”eft hand side of an assignment.

対照的に、同じコードの中にある a や c のようなオブジェクトは名前とメモリアドレスを持ちます。そのようなオブジェクトは通常 lvalue と呼ばれます。代入文の左辺("l"eft hand side)に現れるものだからです。


That’s a simplification of the truth, but it’s generally all you need to know. More precisely, C++ now has five categories of values, but distinguishing them is primarily useful for writing down the language specification, and you can mostly ignore them and just think about “rvalues” for temporary objects without names and whose addresses can’t be taken, and “lvalues” for non-temporary objects that have names and whose addresses can be taken.

これは真実を簡略化していますが、普通の人が知っておく分にはこれで十分です。より正確には、C++ には今や5つの値のカテゴリがありますが、それらを区別するのは言語仕様を書くには便利ですが、普通の人は気にする必要がありません。とにかく "rvalue” は名前を持たない一時的なオブジェクトでそのアドレスを取得すことができない、"lvalue" は一時的ではないオブジェクトで名前を持ちアドレスを取得することができると考えてよいでしょう。


2. How many unnecessary temporary objects can you identify, and how should the programmer fix them?

2. あなたはいくつの不要な一時オブジェクトを見つけられるか?そしてそのプログラマはどのようにそれを直すべきか?

Believe it or not, this short function harbors three obvious cases of unnecessary temporaries or extra copies of objects, two subtler ones, and three red herrings.

信じるかどうかは別として、この短い関数には不要な一時オブジェクトや余分なオブジェクトのコピーが明らかなものが3つ、微妙なものが2つ、そして3つの囮が隠れています。


The parameters are passed by value.

パラメータが値で渡されている。

The most obvious extra copies are buried in the function signature itself:

最も明らかな余分なコピーは関数シグネチャ自体に含まれています:

  string find_addr( list<employee> emps, string name )

The parameters should be passed by const&—that is, const list& and const string&, respectively—instead of by value. Pass-by-value forces the compiler to make complete copy of both objects, which can be expensive and, here, is completely unnecessary.

パラメータは値ではなく const& で渡されるべきです。つまり、それぞれ const list& と const string& となります。値渡しはコンパイラに両方のオブジェクトの完全なコピーを作らせますが、それは高価なものになりえますし、完全に不要です。

Guideline: Prefer passing a read-only parameter by const& if you are only going to read from it (not make a copy of it).

ガイドライン:読み取り専用のパラメータは const& で渡すようにする。(コピーを作らない)


Pedantic note: Yes, with pass-by-value, if the caller passed a temporary list or string argument then it could be moved from rather than copied. But I’m deliberately saying “forces the compiler to make a complete copy” here because no caller is realistically going to be passing a temporary list to find_addr, except by mistake.

厳密には、値渡しであっても呼び出し元が引数として一時オブジェクトを渡したら、それはコピーされるのではなくてムーブされるかもしれません。しかし私は意図的に "コンパイラに完全なコピーを作らせる” と言いました。間違いを除いて呼び出し元が list の一時オブジェクトを find_addr に渡すことは現実的にはないからです。

Non-issue: Initializing with “=”.

問題なし:"=" による初期化

Next we come to the first red herring, in the for loop’s initialization:

次に最初の囮に差し掛かります。for ループの初期化部において:

    for( auto i = begin(emps); /*...*/ )

You might be tempted to say that this code should prefer to be spelled auto i(begin(emps)) rather than auto i = begin(emps), on the grounds that the = syntax incurs an extra temporary object, even if it might be optimized away. After all, as we saw in GotW #1, usually that extra = means the two-step “convert to a temporary then copy/move” of copy-initialization—but recall that doesn’t apply when using auto like this. Why?

あなたはもしかしたら、"このコードは auto i = begin(emps) ではなくて auto i(begin(emps)) と書くべきだよ、= シンタックスはたとえ最適化可能だとはいえ余分な一時オブジェクトを作るよ"、と言いたくなったのではないでしょうか?どのみち、GotW #1 で見たように、通常はその余分な = は2ステップの "一時オブジェクトに変換してからコピーかムーブ" のコピー初期化を意味します。しかし、それはここでのように auto を使っている時には当てはまらなかったことを思い起こしてください。なぜでしょうか?

Remember that auto always deduces the exact type of the initializer expression, minus top-level const and & which don’t matter for conversions, and so… presto! there cannot be any need for a conversion and we directly construct i.

auto は常に初期化式の正確な型を推測します。そしてトップレベルの const と & は変換には関係ありません。そして、、、そう!変換が一切不要なので i を直接構築することができます。

So there is no difference between auto i(begin(emps)) and auto i = begin(emps). Which syntax you choose is up to you, but it depends only on taste, not on temporaries or any other performance or semantic difference.

なので auto i(begin(emps)) と auto i = begin(emps) の間には何も違いがありません。どちらのシンタックスを選ぶかはあなた次第ですが、それは単に好みの問題であって、一時オブジェクトなどのパフォーマンスやセマンティックの違いはありません。

Guideline: Prefer declaring variables using auto. Among other reasons to do so, it naturally guarantees zero extra temporaries due to implicit conversions.

ガイドライン:auto を使って変数を宣言するようにする。そうするべき理由はいくつかあるが、必然的に暗黙の変換による余分な一時オブジェクトが生成されないことが保証される。

The end of the range is recalculated on each loop iteration.

範囲の終端はループの各繰り返しごとに再計算される。

Another potential avoidable temporary occurs in the for loop’s termination condition:

もうひとつの回避可能な一時オブジェクトは for ループの終了条件に見られます:

  for( /*...*/ ; i != end(emps); /*...*/ )

For most containers, including list, calling end() returns a temporary object that must be constructed and destroyed, even though the value will not change.

list を含めほとんどのコンテナにおいて、end() の呼び出しは一時オブジェクトを返します。一時オブジェクトは構築され、破棄されます。たとえその値が変化しないとしてもです。

Normally when a value will not change, instead of recomputing it (and reconstructing and redestroying it) on every loop iteration, we would want to compute the value only once, store it in a local object, and reuse it.

普通、値が変化しないときは、それをループの繰り返しごとに再計算する代わりに(そして再構築と再破棄する代わりに)、その値を一度だけ計算してそれをローカルオブジェクトとして保存しておき、再利用したいと思うはずです。

Guideline: Prefer precomputing values that won’t change, instead of recreating objects unnecessarily.

ガイドライン:値が変化しない場合は、不必要にオブジェクトを再生成するのではなく、前もって計算した値を使うようにする。

However, a caution is in order: In practice, for simple inline functions like list::end() in particular used in a loop, compilers routinely notice their values won’t change and hoist them out of the loop for you without you having to do it yourself. So I actually don’t recommend any change to hoist the end calculation here, because that would make the code slightly more complex and the definition of premature optimization is making the code more complex in the name of efficiency without data that it’s actually needed. Clarity comes first:

しかしながら、注意があります:実際には、list::end() のようなシンプルなインライン関数に対しては、特にループのなかで使われる場合、コンパイラはその値が変化しないことに普通は気づいてそれをループの外に取り出します。あなたが自分でそれをやる必要はありません。なので私は end の計算をループの外に取り出すようにとはおすすめしません。コードが複雑になりますし、早すぎる最適化は効率性の名のもとに実際には必要なデータなしに効率性の名のもとにコードをより複雑にしてしまうからです。明快さが第一です:

Definition: Premature optimization is when you make code more complex in the name of efficiency without data that it’s actually needed.

定義:早すぎる最適化 とは、必要なデータなしに効率性の名のもとにコードを複雑にしてしまうこと

Guideline: Write for clarity and correctness first. Don’t optimize prematurely, before you have profiler data proving the optimization is needed, especially in the case of calls to simple inline calls to short functions that compilers normally can handle for you.

ガイドライン:まず、明快さと正しさのために書く。最適化が必要であることを示すプロファイラのデータが得られるまでは、早すぎる最適化をしない。特にシンプルなインライン関数は通常コンパイラがそれを適切に扱ってくれる。

The iterator increment uses postincrement.

イテレータのインクリメントに後置インクリメントを使っている。

Next, consider the way we increment i in the for loop:

次は、for ループにおいて i をインクリメントする方法について考えてみよう:

  for( /*...*/ ; i++ )


This temporary is more subtle, but it’s easy to understand once you remember how preincrement and postincrement differ. Postincrement is usually less efficient than preincrement because it has to remember and return its original value.

この一時オブジェクトはより気づきにくいが、前置インクリメントと後置インクリメントがどう違うかが一度わかってしまえば理解するのはたやすいことです。後置インクリメントは通常、前置インクリメントよりも効率的ではありません。オリジナルの値を覚えておいて返さなければならないからです。

Postincrement for a class T should normally be implemented using the canonical form as follows:

クラス T に対する後置インクリメントは普通、以下の様な正規化された形式を使って実装されます。

T T::operator++(int)() {
    auto old = *this; // remember our original value
    ++*this;          // always implement postincr in terms of preincr
    return old;       // return our original value
}


Now it’s easy to see why postincrement is less efficient than preincrement: Postincrement has to do all the same work as preincrement, but in addition it also has to construct and return another object containing the original value.

もう後置インクリメントが前置インクリメントよりも効率的でない理由がお分かりでしょう。後置インクリメントは前置インクリメントと全く同じ仕事をする必要がありますが、それに加えてオリジナルの値を保持するもう一つのオブジェクトを作って返す必要もあります。

Guideline: For consistency, always implement postincrement in terms of preincrement, otherwise your users will get surprising (and often unpleasant) results.

ガイドライン:一貫性のため、常に後置インクリメントは前置インクリメントを使って実装する。そうしなければ驚くような(そしてうれしくない)結果をユーザにもたらすことになります。

In the problem’s code, the original value is never used, and so there’s no reason to use postincrement. Preincrement should be used instead. Although the difference is unlikely to matter for a built-in type or a simple iterator type, where the compiler can often optimize away the extra unneeded work for you, it’s still a good habit not to ask for more than you need.

問題のコードでは、オリジナルの値は使われていませんので、後置インクリメントを使う理由はありません。代わりに前置インクリメントが使われるべきです。組込みの型であるかシンプルなイテレータ型であるかといった違いにはほとんど関係なく、コンパイラは最適化により余計なものを取り除いてくれますが、それでも必要以上のことはやらないほうが良いでしょう。

Guideline: Prefer preincrement. Only use postincrement if you’re going to use the original value.

ガイドライン:前置インクリメントを優先的に使用せよ。オリジナルの値を使いたいときだけ後置インクリメントを使用せよ。

“But wait, you’re being inconsistent!” I can just hear someone saying. “That’s premature optimization. You said that compilers can hoist the end() call out of the loop, and it’s just as easy for a compiler to optimize away this postincrement temporary.”

"でも待って、君が言ってることは一貫性がないよ!" 誰かがそう言ったのが聞こえました。"これは早すぎる最適化ってやつだよ。コンパイラは end() をループの外に出してくれるって言ったし、この後置インクリメントの一時オブジェクトを最適化して取り除くのもコンパイラにとってはたやすいことだって言ったじゃない。"

That’s true, but it doesn’t imply premature optimization. Preferring ++i does not mean writing more complex code in the name of performance before you can prove it’s needed—++i is not more complex than i++, so it’s not as if you need performance data to justify using it! Rather, preferring ++i is avoiding premature pessimization, which means avoiding writing equivalently complex code that needlessly asks for extra work that it’s just going to ignore anyway.

それはたしかにそうですが、これは早すぎる最適化ではありません。++i を優先的に使うというのは、パフォーマンスの名のもとにそれが本当に必要であると証明される前に複雑なコードを書くこととは違います。++i は i++ よりも複雑だということはありません。これを使うのを正当化するためにパフォーマンスデータは要りません。逆に、++i を使うことは "早すぎる最悪化(pessimization)" を避けることになります。同程度の複雑さのコードを書くことで、ただ無視されるだけの余計なものを不要に作らせることを回避するからです。

Definition: Premature pessimization is when you write code that is slower than it needs to be, usually by asking for unnecessary extra work, when equivalently complex code would be faster and should just naturally flow out of your fingers.

定義:早すぎる最悪化とは、不要な余計なことをさせるなど、必要以上に遅いコードを書くこと。また同程度の複雑さのコードのほうが速く、それが自然に書くことができること。


The comparison might use an implicit conversion.

比較は暗黙の変換を伴うかもしれない。

Next, we come to this:

次は、ここです:

    if( *i == name )


The employee class isn’t shown in the problem, but we can deduce a few things about it. For this code to work, employee likely must either have a conversion to string or a conversion constructor taking a string. Both cases create a temporary object, invoking either operator== for strings or operator== for employees. (Only if there does happen to be an operator== that takes one of each, or employee has a conversion to a reference, that is, string&, is a temporary not needed.)

employee クラスは問題の中では提示されていませんが、いくつか推測することができます。このコードを動かすためには、employee は string への変換もしくは string を受け取る変換コンストラクタのいずれかを持っていなければならないでしょう。どちらのケースでも一時オブジェクトが作られ、string に対する operator== もしくは employee に対する operator== が起動されます。(operator== が参照(string&)を受け取るか、employee が参照(string&)への変換を持っている場合に限り、一時オブジェクトは必要ありません)

Guideline: Watch out for hidden temporaries created by implicit conversions. One good way to avoid this is to make constructors and conversion operators explicit by default unless implicit conversions are really desirable.

ガイドライン:暗黙の変換によって作られる、隠れた一時オブジェクトに注意しなさい。これを避けるための一つの良い方法は、コンストラクタと変換演算子を explicit にすることです。(暗黙の変換が本当に必要な場合を除く)

Probably a non-issue: return “”.

おそらく問題ではない:return ""

    return "";


Here we unavoidably create a temporary (unless we change the return type, but we shouldn’t; see below), but the question is: Is there a better way?

この場合、一時オブジェクトを作ることは不可避です(ただし戻り値の型を変更することが出来る場合を除く。しかしそうするべきではない。後述)。問題は:もっといい方法はあるか?です。

As written, return “”; calls the string constructor that takes a const char*, and if the string implementation you’re using either (a) is smart enough to check for the case where it’s being passed an empty string, or (b) uses the small string optimization (SSO) that stores strings up to a certain size directly within the string object instead of on the heap, no heap allocation will happen.

書かれてあるとおり、return ""; は string の const char* を引数にとるコンストラクタを呼びます。そしてあなたの使っている string の実装が以下のいずれかの場合、ヒープの確保は起こりません。(a) 空文字列が渡されたことをチェックするような、十分賢い実装になっている。(b) small string optimization (SSO) を使って、ある特定のサイズまでの文字列は直接 string オブジェクトの中に格納し、ヒープを使わないようになっている。

Indeed, every string implementation I checked is smart enough not to perform an allocation here, which is maximally efficient for string, and so in practice there’s nothing to optimize. But what alternatives do we have? Let’s consider two.

たしかに、私のチェックしたすべての string の実装は十分にスマートで、ここではメモリ確保は発生しないようになっていました。これは string としては最大限に効率的です。そして実際に最適化するべきものは何もありません。しかし、他の代替案はないでしょうか?2つ考えてみましょう。


First, you might consider re-spelling this as return “”s; which is new in C++14. That essentially relies on the same implementation smarts to check for empty strings or to use SSO, just in a different function—the literal operator”".

まず、return ""s; と書き換えてみることを考えることができます。これは C++14 で新しく導入されたものです。これは空文字列をチェックするスマートな実装やSSOを使うことと同じものに本質的に頼っています。違うのはリテラル演算子 operator"" です。

Second, you might consider re-spelling this as return { };. On implementations that are both non-smart and non-SSO, this might have a slight advantage over the others because it invokes the default constructor, and so even the most naïve implementation is likely not to do an allocation since clearly no value is needed.

2つ目は、return {}; と書き換えることを考えることができます。スマートでもなく SSO でもない実装においても、これは他の方法に比べてちょっとしたアドバンテージを持つかもしれません。これはデフォルトコンストラクタを起動し、明らかに値が不要なので、最もナイーブな実装であったとしてもメモリ確保をしないでしょう。

In summary, there’s no difference in practice among returning “”, “”s, or { }; use whichever you prefer for stylistic reasons. If your string implementation is either smart or uses SSO, which covers all implementations I know of, there’s exactly zero allocation difference.

まとめると、""、""s もしくは {} を返すことの間には実際的な違いはありません。スタイル上の理由で好きなものをどれでも使えば良いと思います。あなたの使っている string の実装がスマートであるか SSO を使っている場合、そしてそれは私の知る限りすべての実装をカバーしていますが、メモリ確保に関しては全く違いがありません。


Note: SSO is a wonderful optimization for avoiding allocation overhead and contention, and every modern string ought to use it. If your string implementation doesn’t use SSO (as of this writing, I’m looking at you, libstdc++), write to your standard library implementer—it really should.

注:SSO はメモリ確保のオーバーヘッドや競合を回避するための素晴らしい最適化であり、すべての近代的な string が持つべきものです。もしあなたの string の実装が SSO を使っていないなら(これを書いている時点では、libstdc++、君のことを言っているんだよ)、あなたは標準ライブラリの実装者に「マジで実装するべきだ」といってあげてください。


Non-issue: Multiple returns.

問題ではない:複数の return

    return i->addr;
    return "";


This was a second subtle red herring, designed to lure in errant disciples of the “single-entry/single-exit” (SE/SE) persuasion.

これは2つ目の微妙な罠です。”一つの入口/一つの出口" (single-entry/single-exit: SE/SE) という信条の常軌を逸した信奉者を引っ掛けるための釣り餌として用意しました。

I In the past, I’ve heard some people argue that it’s better to declare a local string object to hold the return value and have a single return statement that returns that string, such as writing string ret; … ret = i->addr; break; … return ret;. The idea, they say, is that this will assist the optimizer perform the ‘named return value optimization.’

過去に、ある人々が以下の様な議論をしているのを聞いたことがあります。すなわち、戻り値を保持するローカルの string オブジェクトを宣言して、その string を return する return 文を一つだけ持つのが良い。たとえば string ret; ... ret = i->addr; break; ... return ret; というように書く。このアイディアは、彼らが言うには、オプティマイザが 'named return value optimization(名前付き戻り値最適化)' を行うのを助けるというのです。

The truth is that whether single-return will improve or degrade performance can depend greatly on your actual code and compiler. In this case, the problem is that creating a single local string object and then assigning it would mean calling string’s default constructor and then possibly its assignment operator, instead of just a single constructor as in our original code. “But,” you ask, “how expensive could a plain old string default constructor be?” Well, here’s how the “two-return” version performed on one popular compiler last time I tried it:

真実は、ひとつの return がパフォーマンスを改善するか改悪するかというのは実際のコードとコンパイラに大きく依存しているということです。このケースでは、一つのローカル string オブジェクトを生成してそれに後から値を代入するというのは、string のデフォルトコンストラクタを呼び出し、かつ代入演算子も呼び出すという事になるでしょう。一方、オリジナルのコードではコンストラクタが一度だけ呼び出されます。"でも"、とあなたは言います。"string の単純なデフォルトコンストラクタがどれくらい高価だっていうんだい?" ええと、私が最近試した、あるポピュラーなコンパイラにおいて "2つの return" バージョンのパフォーマンスはこうでした:

  • with optimizations disabled: two-return 5% faster than a “return value” string object
  • with aggressive optimizations: two-return 40% faster than a “return value” string object
  • 最適化オフ:2つのreturn は "戻り値" string オブジェクトよりも 5% 速い
  • 最適化 MAX:2つのreturn は "戻り値" string オブジェクトよりも 40% 速い


Note what this means: Not only did the single-return version generate slower code on this particular compiler on this particular day, but the slowdown was greater with optimizations turned on. In other words, a single-return version didn’t assist optimization, but actively interfered with it by making the code more complex.

これが意味するところに注意:1つの return バージョンはこの特定の日にこの特定のコンパイラにおいて遅いコードを生成しただけではなく、最適化を ON にしたときにスローダウンが大きくなりました。言い換えると、1つの return バージョンは最適化を支援しませんでした。むしろコードを複雑にすることによって積極的に最適化の邪魔をしました。

In general, note that SE/SE is an obsolete idea and has always been wrong. “Single entry,” or the idea that functions should always be entered in one place (at their start) and not with goto jumps from the caller’s code directly to random places inside the function body, was and is an immensely valuable advance in computer science. It’s what made libraries possible, because it meant you could package up a function and reuse it and the function would always know its starting state, where it begins, regardless of the calling code. “Single exit,” on the other hand, got unfairly popular on the basis of optimization (‘if there’s a single return the compiler can perform return value optimization better’—see counterexample above) and symmetry (‘if single entry is good, single exit must be good too’) but that is wrong because the reasons don’t hold in reverse—allowing a caller to jump in is bad because it’s not under the function’s control, but allowing the function itself to return early when it knows it’s done is perfectly fine and fully under the function’s control. To put the final nail in the coffin, note that “single exit” has always been a fiction in any language that has exceptions, because you can get an early exceptional return from any point where you call something that could throw an exception.

一般的に、SE/SE は時代遅れのアイディアで、常に間違っていました。”一つの入口" 、もしくは関数には常にひとつの場所(開始地点)から入ってくるべきであって呼び出し元のコードから直接 goto ジャンプで関数本体の内側のデタラメな場所から入ってくるべきではないという考えは、コンピュータサイエンスにおける偉大で価値のある進歩です。関数は呼び出し元のコードに関係なく、常にその開始状態を知っているので、そのおかげで関数をパッケージして再利用することができてライブラリを作ることができます。一方、"一つの出口" は不当にポピュラーになってしまいました。最適化('return がひとつだけならコンパイラは戻り値の最適化をよりうまくやれる'というもの - 上の反例を参照)や対称性('一つの入口 が良いのなら、一つの出口もまた良いのだろう’)にもとづいていますが、それは間違いです。それらの理由は逆に成り立たないからです。呼び出し元からジャンプして入ってくることを許すのは悪いことです。その関数のコントロールの及ばないことだからです。しかしその関数から早く return することは、それがいつ行われるかがわかっていれば全く問題ありません。その関数のコントロール下にあることだからです。とどめに、"一つの出口" は例外機構を持ついかなる言語においても、常にフィクションに過ぎません。例外を投げる可能性のあるものを呼び出すところではどこでも例外によって関数から抜けだしてしまうことができるからです。

Non-issue: Return by value.

問題なし:値による return

Which brings us to the third red herring:

3番目の罠です:

string find_addr( /*...*/ )


Because C++ naturally enables move semantics for returned values like this string object, there’s usually little to be gained by trying to avoid the temporary when you return by value. For example, if the caller writes auto address = find_addr( mylist, “Marvin the Robot” );, there will be at most a cheap move (not a deep copy) of the returned temporary into address, and compilers are allowed to optimize away even that cheap move and construct the result into address directly.

C++ はこの string オブジェクトのような戻り値に対して当然のようにムーブセマンティクスを有効にしますので、値を返すときに一時オブジェクトを避けようとしても通常は得るものはほとんどないでしょう。たとえば、呼び出し元が auto address = find_addr(mylist, "Marvin the Robot"); と書いたとすれば、戻り値の一時オブジェクトは address に対してディープコピーではなくせいぜい安価なムーブになるでしょうし、コンパイラはその安価なムーブを最適化して取り除いて address に直接結果を構築することもできます。

But what if you did feel tempted to try to avoid a temporary in all return cases by returning a string& instead of string? Here’s one way you might try doing it that avoids the pitfall of returning a dangling reference to a local or temporary object:

もしあなたに、すべての return で string を使う代わりに string& を返すことで一時オブジェクトを回避しようとする魔が差したとしたらどうでしょう?ローカルオブジェクトや一時オブジェクトへの宙ぶらりんの(dangling)参照を返してしまう落とし穴を回避しながらあなたが試すかもしれない一つの方法はこうなるでしょう:

const string& find_addr( /* ... */ ) {
    for( /* ... */ ) {
        if( /* found */ ) {
            return i->addr;
        }
    }
    static const string empty;
    return empty;
}


To demonstrate why this is brittle, here’s an extra question:

これが脆弱であることを示すために、もう一つ問題です:

For the above function, write the documentation for how long the returned reference is valid.

上記の関数において、返された参照がどのくらいの期間有効であるかを説明するドキュメントを書きなさい。

Go ahead, we’ll wait.

さあどうぞ。待ってます。


Done? Okay, let’s consider: If the object is found, we are returning a reference to a string inside an employee object inside the list, and so the reference itself is only valid for the lifetime of said employee object inside the list. So we might try something like this (assuming an empty address is not valid for any employee):

終わりましたか?オーケー、それでは考えてみましょう:もし object が見つかったら、list の中の employee オブジェクトの中の string への参照を返すことになります。したがってその参照自身は、その list の中の employee オブジェクトの有効期間の間だけ有効です。したがってあなたはこのようなことを言ってみるかもしれません(空の住所はどんな employee に対しても有効でないと仮定します):

“If the returned string is nonempty, then the reference is valid until the next time you modify the employee object for which this is the address, including if you remove that employee from the list.”

"返される文字列が空でない場合、その参照は、その address を持っている employee オブジェクトが次に変更される時まで有効です。変更にはその employee オブジェクトが list から削除されることも含みます。”

Those are very brittle semantics, not least because the first (but far from only) problem that immediately arises is that the caller has no idea which employee that is—not only doesn’t he have a pointer or reference to the right employee object, but he may not even be able to easily figure out which one it is if two employees could have the same address. Second, calling code can be notoriously forgetful and careless about the lifetimes of the returned reference, as in the following code which compiles just fine:

とても脆弱なセマンティクスです。特に、数ある問題のうちすぐに起こる最初の問題は、呼び出し元はその employee オブジェクトが何かわかりません。正しい employee オブジェクトへのポインタも参照もわからないだけでなく、2つの employee が同じ address を持っていたらそのどちらなのかを簡単に判別することもできません。2つ目の問題は、呼び出し元のコードというのは、返されたリファレンスの有効期間について、すぐに忘れてしまって気にもしないものだということです。コンパイルは問題なく通る以下のコードのように:

auto& a = find_addr( emps, "John Doe" );  // イェイ、一時オブジェクトを回避したぜ!
emps.clear();
cout << a;                                // おっと

When the calling code does something like this and uses a reference beyond its lifetime, the bug will typically be intermittent and very difficult to diagnose. Indeed, one of the most common mistakes programmers make with the standard library is to use iterators after they are no longer valid, which is pretty much the same thing as using a reference beyond its lifetime; see GotW #18 for details about the accidental use of invalid iterators.

呼び出し元のコードがこのようなことをしていて、参照をその有効期間を超えて使っていると、そのバグはたいてい、時々しか発生せずにとても解析のしづらいものとなります。標準ライブラリでプログラマが犯すもっとも一般的な失敗は、イテレータがもう有効でないのに使ってしまうことですが、参照をその有効期間を超えて使ってしまうというのはそれととても良く似ています。誤って無効なイテレータを使ってしまうことの詳細について GotW #18 を見てください。

Summary まとめ


There are some other optimization opportunities. Ignoring these for now, here is one possible corrected version of find_addr which fixes the unnecessary temporaries. To avoid a possible conversion in the employee/string comparison, we’ll assume there’s something like an employee::name() function and that .name() == name has equivalent semantics.

他にもいくつか最適化できるところがあります。今はそれは無視して、不要な一時オブジェクトを直したバージョンの find_addr の一例をお見せします。employee と string の比較における変換を避けるために、employee::name() のような関数があって .name() == name が等価なセマンティクスを持っていると仮定します。

Note another reason to prefer declaring local variables with auto: Because the list parameter is now const, calling begin and end return a different type—not iterators but const_iterators—but auto naturally deduces the right thing so you don’t have to remember to make that change in your code.

auto を使ってローカル変数を宣言するべきであるもう一つの理由:list 引数は const になりましたので begin と end の呼び出しは違う型を返すようになりました。iterator 型ではなく const_iterator 型です。しかし auto は自然に正しい型を推測しますので、その部分について忘れずにコードを変更する必要がありません。

string find_addr( const list<employee>& emps, const string& name ) {
    for( auto i = begin(emps);  i != end(emps); ++i ) {
        if( i->name() == name ) {
            return i->addr;
        }
    }
    return "";
}

Acknowledgments 謝辞

Thanks in particular to the following for their feedback to improve this article: “litb1,” Daan Nusman, “Adrian,” Michael Marcin, Ville Voutilainen, Rick Yorgason, “kkoehne,” and Olaf van der Spek.

この記事をより良くするための以下の各位からのフィードバックに対し、特に感謝する: “litb1,” Daan Nusman, “Adrian,” Michael Marcin, Ville Voutilainen, Rick Yorgason, “kkoehne,” そして Olaf van der Spek。

mruby on Tizen 2.2 beta

Tizen プロジェクトがキャンセルされたとか何とかいう噂がまことしやかに囁かれているようですが、Tizen は今のところ元気です。何事もなかったかのように淡々とプロジェクトは進行しています。

さて、Tizen SDK 2.2 beta もリリースされたことですので、さっそく mruby をビルドして動かしてみました。

build_config.rb に以下の内容を追加します。

といっても、前回の2.1の時からの変更点は rootstrap のディレクトリ名がちょっと変わったくらいです。

- TIZEN_GCC_I386_EMULATOR_BASE = "#{TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-emulator-2.1.native"
+ TIZEN_GCC_I386_EMULATOR_BASE = "#{TIZEN_SDK}/platforms/tizen2.2/rootstraps/tizen-emulator-2.2.native"

- TIZEN_GCC_ARM_DEVICE_BASE = "#{TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-device-2.1.native"
+ TIZEN_GCC_ARM_DEVICE_BASE = "#{TIZEN_SDK}/platforms/tizen2.2/rootstraps/tizen-device-2.2.native"


実行してみた結果:

(host)$ cd mruby
(host)$ ./minirake
(host)$ sdb -e root on
(host)$ sdb -e push build/tizen-x86/ /opt/apps/mruby/
(host)$ sdb -e shell
sh-4.1# /opt/apps/mruby/bin/mruby -e 'system "cat /etc/tizen-release"'
Tizen release 2.2.0 (Tizen)

今日から使える! 液晶マイコンボード付きmruby学習キット EAPL-Trainer mruby

今日から使える! 液晶マイコンボード付きmruby学習キット EAPL-Trainer mruby


Arduino イーサネットシールド

Arduino イーサネットシールド


Rubyプログラミング入門

Rubyプログラミング入門


たのしいRuby 第3版

たのしいRuby 第3版

Ubuntu 12.04 で特定のポインティングデバイスからの入力だけマッピングを変更する方法

.Xmodmap を使ってマウスのボタンのマッピングを変更すると、すべてのポインティングデバイスからの入力を一律で変更してしまいます。

たとえば、トラックパッドが付いているノートパソコンに USB マウスもつないでいる状態だと、ポインティングデバイスが 2 つある状態になりますが、.Xmodmap で書いた pointer 設定は両方のデバイスからの入力に適用されてしまいます。

そうなると、「トラックパッドは natural scrolling にしたいけどマウスは従来通りにしたい」というような希望があったとしたらそれが実現できないことになってしまいます。

そこで xinput コマンドを使用します。

まずは

xinput list

で自分の PC に接続されている入力デバイスの一覧を取得します。

そしてその中からターゲットとなるポインティングデバイスの id を見つけます。

つぎに以下のようなコマンドを入力します。

xinput set-button-map <ID> 1 2 3 4 5 6 7 8 9 10 11 12


<ID> には xlinput list で調べた ID を入れます。
その後ろの 1 〜 12 はボタンの設定です。(ホイールを回した時も、回転方向に応じたボタンが押されていることになっているようです)

私のマウスの場合は 4 と 5 がスクロールの上下に対応していたので、そこを入れ替えれて natural scrolling が実現できました。

GotW #1 Solution: Variable Initialization – or Is It?(勝手訳:変数の初期化-もしくは?)

前回の投稿から少し間が開いてしまいましたが、第1回めの GotW の翻訳です。

例によって原文著者(Herb Sutter 氏)の許可は得ていませんし、私の英訳がヒドいクオリティである(用語の統一がとれていないとか、誤訳が含まれているとか)かもしれませんのでそこのところはご理解いただければと思います。


原文:http://herbsutter.com/2013/05/09/gotw-1-solution/

This first problem highlights the importance of understanding what you write. Here we have a few simple lines of code—most of which mean something different from all the others, even though the syntax varies only slightly.

この最初の問題は、あなたが書くものを理解することの重要性を浮き彫りにします。数行のシンプルなコードを提示しますが、ほとんどの行はたとえシンタックス上の違いがわずかだとしても他のすべての行と何かしら異なる意味を持ちます。

Problem 問題

JG Question 見習いグルへの質問

1. What is the difference, if any, among the following?
1. 以下のうち、違いがあるとしたらそれは何か?

widget w;                   // (a)
widget w();                 // (b)
widget w{};                 // (c)
widget w(x);                // (d)
widget w{x};                // (e)
widget w = x;               // (f)
widget w = {x};             // (g)
auto w = x;                 // (h)
auto w = widget{x};         // (i)
Guru Questions

グルへの質問

2. What do each of the following lines do?
2. 以下のそれぞれの行は何をするか?

vector<int> v1( 10, 20 );   // (a)
vector<int> v2{ 10, 20 };   // (b)


3. Besides the cases above, what other benefits are there to using { } to initialize objects?
3. 上記のケース以外で、オブジェクトを初期化するために {} を使うことにどのような効能があるか?


4. When should you use ( ) vs. { } syntax to initialize objects? Why?
4. オブジェクトを初期化するために {} ではなく () を 使うべきときはいつか?それはなぜか?



Solution 解答

This puzzle demonstrates several things:

  • The difference between default initialization, direct initialization, copy initialization, and list initialization.
  • The difference between using ( ) and using { } for initialization.
  • A red herring that isn’t initialization at all, and which modern C++ entirely avoids.

この問題はいくつかのことを明らかにします:

  • デフォルト初期化、ダイレクト初期化、コピー初期化、およびリスト初期化の違い
  • 初期化に () を使うことと {} を使うことの違い
  • 全くもって初期化ではないという罠と、モダンな C++ がそれを完全に回避していること

But, most important of all: If you stick to two simple Guidelines, which we’ll cover in #4, you can ignore most of these cases and the rules are pretty simple and deliver efficient performance by default.

しかし最も重要なのは、あなたが #4 でカバーされる 2 つのシンプルなガイドラインさえ守っていれば、これらのケースのほとんどを無視することができるということと、ルールはとてもシンプルであるということと、デフォルトで効率面でのパフォーマンスをもたらしてくれるということです。


1. What is the difference, if any, among the following?
1. 以下のうち、違いがあるとしたらそれは何か?

Let’s consider the cases one by one.

それぞれのケースを1つずつ考えてみましょう。

(a) is default initialization.
(a) はデフォルト初期化。

widget w;                   // (a)

This code declares a variable named w, of type widget. For most types, it is initialized using the default constructor widget::widget().

このコードは widget 型の w という名前の変数を宣言します。ほとんどの型において、デフォルトコンストラクタ widget::widget() を使って初期化されます。


Note that w is not initialized and contains garbage values if widget happens to be a built-in type like int, or a simple “int-like” class type with what’s called a “trivial” default constructor—a type that relies on the compiler-generated default constructor, has no virtual functions or virtual base classes or data member initializers, and all its bases and members satisfy the same restrictions.

widget が int のような組み込み型である場合、もしくはシンプルな "int 風" クラス型である場合、w は初期化されずゴミの値を持つということに注意してください。ここでいう "int 風" クラス型とは、"trivial" デフォルトコンストラクタをもち、コンパイラの生成するデフォルトコンストラクタに依存し、仮想関数や仮想基底クラスやデータメンバイニシャライザを持たず、そのすべての基底クラスとメンバが同じ制約を満たすものです。

(b) is a “vexing” red herring, now mostly a historical curiosity.
(b) はウザい罠であり、現時点ではほとんど歴史的な珍しい存在です。

widget w();                 // (b)


This is a pre-modern C++ pitfall: At first glance, it may look like just another variable declaration calling a default constructor widget::widget(); in reality, thanks to a grammar ambiguity, it’s a function declaration for a function named w that takes no parameters and returns a widget object by value. (If you can’t see this at first, consider that the above code is no different from writing something like int f(); which is clearly a function declaration.)

これは前近代的 C++ の落とし穴です。一見、デフォルトコンストラクタ widget::widget() を呼んでいる他の変数宣言と同じように見えます。実際には、文法の曖昧さのため、これは w という名前で引数をとらず widget オブジェクトを値で返す関数の宣言です。(もし最初はそう見えなかったとしても、上記のコードは int f(); のような明らかな関数宣言と何も違いがないということを考えてみてください)

Lest you think “aw, but those ( ) parentheses are redundant, it’s the programmer’s own fault for not just writing widget w; there!”, note that the same problem arises in those occasional cases where you think you’re initializing a variable with temporary objects:

ここであなたが「あぅ、でもその () は冗長だから、それは widget w; って書かなかったプログラマの過失だよね!」と考えるといけないので、もう一つの例をお見せします。これはテンポラリオブジェクトで変数が初期化されると考えられるかもしれませんが同じ問題が起こるケースです。

// 同じ問題(gadget と doodad は型)
//
widget w( gadget(), doodad() );  // 落とし穴: 変数宣言ではない

Scott Meyers long ago named this “C++’s most vexing parse,” because the standard resolves the parsing ambiguity by saying: “if it can be a function declaration, it is.”
スコット・メイヤーズはずっと昔、これを "C++ の最もウザいパース" と呼びました。C++ 標準はパース時の曖昧さについて、こう言って解決しているからです:"もしそれが関数宣言でありうるなら、それは関数宣言である"


The good news is that this is now mostly a historical curiosity, not something you should encounter in new code, because C++11 removed this pitfall. Note that C++11 does not change the meaning of the code—C++11 has great backward compatibility with C++98, including that this ambiguity still has the same meaning it always had. Rather, C++11 solves this by providing a syntax that supersedes case (b) in nearly all cases, so that we don’t need to ever fall into this pit anymore:

良い知らせは、これはすでに歴史的に珍しいものとなっていて、あなたが新しいコードを書いている時に出会うべきものではないということです。C++ はこの落とし穴を取り除きました。といっても、C++11 はそのコードの意味を変えてはいないことに注意してください。C++11 は C++98 に対し素晴らしい後方互換性を持っています。この曖昧さについてもこれまでと同じ意味を持っています。C++11 はほとんどすべてのケースでケース (b) に取って代わるシンタックスを提供することでこれを解決します。これでもう私たちはこの落とし穴にこれ以上ハマる必要はなくなるのです:

(c) is non-vexing and clear.
(c) はウザくないし明快。

widget w{};                 // (c)


Here we have the first reason to prefer { } to ( ): For any class type widget, line (c) does the “best parts” of (a) and (b)—it always initializes the variable, and is never ambiguous with a function declaration. No vex, no fuss, no muss.

これが () よりも {} を好むべき第一の理由です。いかなるクラス型 widget に対しても、行 (c) は (a) と (b) の "良いとこ取り" をします。常に変数を初期化し、関数宣言と曖昧ではありません。ウザくないし、面倒なことは何もありません。

“Aha, but wait, it’s not that simple!” someone might object. “What if widget has a constructor that takes a std::initializer_list? Those are greedy (preferred), so if widget has one of those wouldn’t this call that?”

"アハ、でも待って、そんなにシンプルじゃないよ!" 誰かが異議を唱えるかもしれません。"widget がstd::initializer_list を取るコンストラクタを持っていたらどう?そいつは優先されるから、widget がそれを持ってたらそっちが呼ばれるんじゃないの?"


The answer is no, this really is just as simple as it looks, because the standard is explicit that an empty { } list means to call the default constructor if available. However, it’s good to be aware of initializer_lists, so let’s talk about those next.

答えは No です。これは見たとおりシンプルです。標準には、空の {} リストはデフォルトコンストラクタがあればそれを呼ぶと明示されているからです。しかしながら、initializer_list に注意するのはいいことです。というわけで次はそれについて話しましょう。

(d) and (e) are direct initialization.
(d) および (e) はダイレクト初期化。

Now let’s consider cases where we actually initialize w from some existing variable:

今度は w を何らかの既存の変数から初期化する場合を考えましょう:

widget w(x);                // (d)
widget w{x};                // (e)


Assuming x is not the name of a type, these are both direct initialization. That’s because the variable w is initialized “directly” from the value of x by calling widget::widget(x). If x is also of type widget, this invokes the copy constructor. Otherwise, it invokes a converting constructor.

x は型の名前ではないとすると、両方ともダイレクト初期化です。widget::widget(x) を呼ぶことで x の値から w が "直接" 初期化されるからです。x も widget 型の変数であるとするならば、これはコピーコンストラクタを起動します。そうでなければ変換コンストラクタを起動します。


However, note that the syntax {x} creates an initializer_list. If widget has a constructor that takes an initializer_list, that constructor is preferred; otherwise, if widget has a constructor that takes whatever type x is (possibly with conversions), that constructor is used.

しかしながら、シンタックス {x} は initializer_list を生成することに注意してください。widget が initializer_list を取るコンストラクタを持っている場合、そのコンストラクタが優先されます。それ以外の場合、widget が(変換を伴ったとしても)x の型を取るコンストラクタを持っているなら、そのコンストラクタが使用されます。


There are two major differences that make (e) superior to (d): First, like (c), syntax (e) is unambiguous and avoids the vexing parse. If x is a type name, then (d) is a function declaration even if there is also a variable named x in scope (see above), whereas (e) is never a function declaration.

(d) よりも (e) が優れている2つの大きな違いがあります:一つ目は、(c) と同様、シンタックス (e) は曖昧ではなく、ウザいパースを回避します。x が型の名前である場合、(d)は関数宣言になってしまいます。x という名前の変数がスコープ内にあったとしてもです(上記を参照)。それに対し、(e) は関数宣言になることはありません。


Second, syntax (e) is safer because it does not allow narrowing (a.k.a. “lossy”) conversions that are otherwise allowed for some built-in types. Consider:

2つ目に、シンタックス (e) はより安全です。ナローイング(narrowing) (データ損失を伴う) を許していないからです。

int i1( 12.345 );           // ok: .345 は捨てられてしまいます。いずれにせよ好ましくありません
int i2{ 12.345 };           // error: データ損失を伴う暗黙のナローイングが起こりうる


(f) and (g) are copy initialization and copy list initialization.
(f) と (g) はコピー初期化とコピーリスト初期化

This brings us to our final two non-autocases:

これは auto を使っていない残り2つのケースです:

widget w = x;               // (f)


This is called “copy initialization.” Conceptually, the variable w is initialized using widget‘s move or copy constructor, possibly after calling another function to convert the argument implicitly (explicit conversions won’t be invoked here).

これは"コピー初期化"と呼ばれます。概念的には、変数 w は widget のムーブコンストラクタかコピーコンストラクタを使って初期化されます。場合によっては引数を暗黙的に変換するための他の関数を呼んだ後でかもしれません(明示的変換はここでは起動しません)。

Common Mistake: This is always initialization; it is never assignment, and so it never calls T::operator=(). Yes, I know there’s an “=” character in there, but don’t let that throw you — that’s just a syntax holdover from C, not an assignment operation.

ありがちな間違い:これは常に初期化です。代入ではありません。T::operator=() を呼び出しもしません。そう、”=” の文字がそこにあるのにもかかわらずです。これは C から持ち越されたただの文法であり、代入操作ではありません。

Here are the semantics:

セマンティクスはこうです:

If x is of type widget, line (f) means the same as (d) widget w(x); except that explicit constructors cannot be used. It’s guaranteed that only a single constructor is called.

x が widget 型である場合、行(f) は (d) widget w(x); と同じ意味になります。ただし、explicit コンストラクタが使われることはありません。単一のコンストラクタのみが呼び出されることは保証されています。


If x is of some other type, conceptually the compiler first implicitly converts x to a temporary widget object, then move-constructs w from that temporary rvalue, using copy construction as “the slow way to move” as a backup if no better move constructor is available. Assuming that an implicit conversion is available, (f) means the same as widget w( widget(x) );.

x が他の何かの型である場合、概念的にはコンパイラはまず暗黙的に x をテンポラリな widget 型のオブジェクトに変換し、それからそのテンポラリな rvalue から w をムーブコンストラクトします。もしちょうど良いムーブコンストラクタがない場合、バックアップとして "ムーブするための遅い方法" としてコピーコンストラクションが使われます。暗黙の変換があるならば、(f) は widget w(widget(x)); と同じになります。


Note that I said “conceptually” a few times above. That’s because practically compilers are allowed to, and routinely do, optimize away the temporary and, if an implicit conversion is available, convert (f) to (d), thus optimizing away the extra move operation. However, even when the compiler does this, the widget copy constructor must still be accessible, even if is not called—the copy constructor’s side effects may or may not happen, that’s all.

上記で何度か "概念的に" といったことに注意してください。”実際的には” コンパイラはそのテンポラリを最適化して取り除くことが許されていますし、普通のコンパイラはそうしますし、もし暗黙の変換があれば (f) を (d) に変換しますので、そのムダなムーブ操作が最適化されて取り除かれます。しかしながら、コンパイラがそうするからといって、widget コピーコンストラクタはアクセス可能でなければなりません。たとえ呼ばれることがなく、コピーコンストラクタの副作用があろうがなかろうが。以上。


Now note the related syntax that adds “=“:

さて、今度は関連するシンタックスとして "=" を加えたものに着目しましょう。

widget w = {x};             // (g)


This is called “copy list initialization.” It means the same as widget w{x}; except that explicit constructors cannot be used. It’s guaranteed that only a single constructor is called.

これは "コピーリスト初期化" と呼ばれます。これは widget w{x}; と同じ意味です。ただし、explicit コンストラクタは使われません。単一のコンストラクタのみが呼び出されることが保証されています。

(h) and (i) are also copy initialization, but simpler.
(h) と (i) もコピー初期化ですが、よりシンプル

auto w = x;                 // (h)
auto w = widget{x};         // (i)

The semantics are just like (f) and (g), except simpler to teach, learn, and use because using auto guarantees the right-hand expression’s type will be deduced exactly. Note that the (i) syntax works fine for both implicit and explicit conversions.

セマンティクスは (f) や (g) と同様ですが、教えたり習ったり使ったりするにはシンプルな点が異なります。auto を使っているので右辺の式の型が推定されることが保証されるからです。(i) シンタックスは暗黙のおよび明示的な変換が共にうまく働くことに注意してください。


Line (h) means the same as (d), type_of_x w(x);. Only a single copy constructor is called. This is guaranteed to stay true as the program evolves: Because line (h) does not commit to an explicit type, it is guaranteed to be both maximally efficient because there can be no conversion involved, and maximally robust under maintenance as the type of w “auto”-matically tracks the type of x which may change as the program is maintained.

行 (h) は (d) と同じ意味で、<xの型> w(x); です。一度だけコピーコンストラクタが呼び出されます。これはプログラムが変更されても真であることが保証されます。行 (h) は明示的な型を確定しておらず、変換が発生しないので最大限に効率的であることと、プログラムが保守されて x の型が変わっても w の型が自動的に追随するので最大限にロバストであるからです。

Line (i) is the most consistent spelling when you do want to commit to a specific type and explicitly request a conversion if needed, and once again the { } syntax happily avoids lossy narrowing conversions. In practice on most compilers, only a single constructor is called—similarly to what we saw with (f) and (g), conceptually there are two constructor calls, a converting or copy constructor to create a temporary widget{x} followed by a move to move it to w, but compilers routinely elide the latter.

行 (i) は、特定の型を確定したい場合に最も一貫性のある書き方です。必要に応じて明示的な型変換が行われ、なおかつデータ損失を伴うナローイング変換を避ける {} が使われています。実際にはほとんどのコンパイラは、(f) や (g) で見てきたのと同様、コンストラクタを一度だけ呼び出します。概念的には2回のコンストラクタ呼び出し - widget{x} の一時オブジェクトを生成するための変換コンストラクタかコピーコンストラクタと、wにそれをムーブするためのムーブコンストラクタ - がありますが、コンパイラはお決まりのパターンとして後者を取り除きます。

In general, I recommend that you try out these two forms, and increasingly prefer using them as you grow comfortable with them. I’m at the point where I’m now inclined to write virtually all of my local variable declarations this way. (I know some of you will be skeptical about this broad claim—more on “the auto question” in another GotW.)

一般的に、これらの2つの形をお試しになることをお勧めします。これらを好んで使うことが多くなるに従い、より満足度も増加することでしょう。私自身、ローカル変数を宣言するほとんどすべての箇所でこの方法を使うようになりました。(この口幅ったい言い方に対して懐疑的な方もいるかもしれません。"auto" についての GotW をお楽しみに)


2. What do each of the following lines do?
2. 以下の各行は何をするか?

In the Question 2 code, we’re creating a vector and passing the arguments 10 and 20 to its constructor—in the first case as ( 10, 20 ) and in the second case as { 10, 20 }.

質問2のコードでは、vector を生成して引数 10 と 20 をそのコンストラクタに渡しています。1つ目では (10, 20) として、2つ目では {10,20} として。

Both will call a constructor, but which one(s)? Well, vector has several constructors that can take two parameters, but only two could be correctly called with the parameters 10 and 20. Ignoring defaulted optional allocator parameters for simplicity, the two constructors are:

両方ともコンストラクタを呼び出します。ではどのコンストラクタを呼び出すのでしょう?ええと、vector は 2 つの引数を受け取るいくつかのコンストラクタを持っていますが、引数 10 と 20 で正しく呼び出されるものは 2 つだけです。デフォルトで指定されるオプションのアロケータ引数は、簡素化のために無視します。その2つのコンストラクタとは:

vector( size_t n, const int& value );    // A: value の n 個のコピー
vector( initializer_list<int> values );  // B: values のコピー


There are two simple C++ rules that tell us which one will be called for the code in question:

  • The syntax { /*…*/ } used in an expression context gives you an initializer_list.
  • Constructors that take an initializer_list are preferred over other constructors, and so can hide other constructors that might otherwise be viable.

2つのシンプルな C++ のルールが、質問のコードに対してどのコンストラクタが呼ばれるのかを教えてくれます。


Armed with those two tidbits, the answer is simple:

この2つで武装して、答えはシンプルに:

vector<int> v1( 10, 20 );    // (a) A が呼ばれる: 値 20 のコピー が 10 個
assert( v1.size() == 10 );

vector<int> v2{ 10, 20 };    // (b) B が呼ばれる: 値 10 と 20
assert( v2.size() == 2 );


3. Besides the cases above, what other benefits are there to using { } to initialize objects?
3. 上記のケース以外で、オブジェクトを初期化するために {} を使うことにどのような効能があるか?

For one thing, it’s called “uniform initialization” because it’s, well, uniform—the same for all types, including aggregate structs and arrays and std:: containers, and without the “vexing parse” annoyance:

一つとして、”単一形式(uniform)初期化" があります。それは、構造体や配列や std:: コンテナを含むすべての型に対して同じ形式が使えて、しかもあの "ウザいパース" が起こりません。

struct mystruct { int x, y; };

// C++98
rectangle w( origin(), extents() );       // おっと、ウザいパース
complex<double> c( 2.71828, 3.14159 );
mystruct        m = { 1, 2 };
int             a[] = { 1, 2, 3, 4 };
vector<int>     v;                              // 困った、初期化するには
for( int i = 1; i <= 4; ++i ) v.push_back(i);   //   もっとコードが必要だ

// C++11 (注意: "=" は必須ではない)
rectangle       w   = { origin(), extents() };
complex<double> c   = { 2.71828, 3.14159 };
mystruct        m   = { 1, 2 };
int             a[] = { 1, 2, 3, 4 };
vector<int>     v   = { 1, 2, 3, 4 };

And note that this isn’t just an aesthetic issue. Consider writing generic code that should be able to initialize any type… and while we’re at it, let’s gratuitously use perfect forwarding as an example:

これは美的問題だけにとどまりません。どんな型でも初期化できるべきであるようなジェネリックなコードを書くことを考えてみましょう。... 忙しいのでとにかくパーフェクトな forwarding を例として取り上げましょう:

template<typename T, typename ...Args>
void forwarder( Args&&... args ) {
    // ...
    T local = { std::forward<Args>(args)... };
    // ...
}
forwarder<int>            ( 42 );                  // ok
forwarder<rectangle>      ( origin(), extents() ); // ok
forwarder<complex<double>>( 2.71828, 3.14159 );    // ok
forwarder<mystruct>       ( 1, 2 );                // ok {} のおかげ
forwarder<int[]>          ( 1, 2, 3, 4 );          // ok {} のおかげ
forwarder<vector<int>>    ( 1, 2, 3, 4 );          // ok {} のおかげ


The last three lines would not be legal if forwarder used ( ) initialization syntax internally.

最後の3行は forwarder が () 初期化シンタックスを内部的に使用していると、成立しません。


The new { } syntax works pretty much everywhere, including to initialize members:

新しい {} シンタックスはどこででもうまく動きます。メンバの初期化のときも:

widget::widget( /*...*/ ) : mem1{init1}, mem2{init2, init3} { /*...*/ } 


And, as icing on the take, it’s often just plain convenient to pass function arguments, or return a value, without a type-named temporary:

関数の引数に渡したり、値を返したりするときに、一時オブジェクトの型名を書かなくて良くなるので素直に便利です。

void draw_rect( rectangle );

draw_rect( rectangle(origin, selection) );         // C++98
draw_rect({ origin, selection });                  // C++11

rectangle compute_rect() {
    // ...
    if(cpp98) return rectangle(origin, selection);  // C++98
    else      return {origin, selection};           // C++11
}


4. When should you use ( ) vs. { } syntax to initialize objects? Why?
4. オブジェクトを初期化するために {} ではなく () を 使うべきときはいつか?それはなぜか?


Here’s the simple guideline:

シンプルなガイドライン:


Guideline: Prefer to use initialization with { }, such as vector v = { 1, 2, 3, 4 }; or auto v = vector{ 1, 2, 3, 4 };, because it’s more consistent, more correct, and avoids having to know about old-style pitfalls at all. In single-argument cases where you prefer to see only the = sign, such as int i = 42; and auto x = anything; omitting the braces is fine. …

ガイドライン:{} による初期化を好んで使え。たとえばvector v = { 1, 2, 3, 4 };もしくはauto v = vector{ 1, 2, 3, 4 };のように。より一貫性があり、より正しく、古いスタイルの落とし穴についての知識を全く持たなくてもよくなる。引数が1つだけのケースでは、= 記号を使いたくなるが、この場合はint i = 42;やauto x = anything;のように {} を使わなくても構わない。


That covers the vast majority of cases. There is only one main exception:

これはほとんどのケースをカバーします。1つだけの主要な例外は:


… In rare cases, such as vector v(10,20); or auto v = vector(10,20);, use initialization with ( ) to explicitly call a constructor that is otherwise hidden by an initializer_list constructor.

...レアなケースとして、vector v(10,20);やauto v = vector(10,20);のように () による初期化を使う。そうしなければ、初期化リストコンストラクタによって隠されてしまうコンストラクタを明示的に呼び出すことができない。

However, the reason this should be generally “rare” is because default and copy construction are already special and work fine with { }, and good class design now mostly avoids the resort-to-( ) case for user-defined constructors because of this final design guideline:

しかしながら、これが一般的には "レア" なのは、デフォルトコンストラクタとコピーコンストラクタがすでに特別であり、{} でうまく動くからで、よいクラスのデザインはいまやこの最後のデザインガイドラインのためにユーザ定義のコンストラクタのために () を使うことをほとんど避けています。


Guideline: When you design a class, avoid providing a constructor that ambiguously overloads with an initializer_list constructor, so that users won’t need to use ( ) to reach such a hidden constructor.

ガイドライン:クラスをデザインするとき、initializer_list コンストラクタで曖昧にオーバーロードするようなコンストラクタを提供することを避け、ユーザがそのような隠されるコンストラクタを呼び出すために () を使う必要がないようにする。


Acknowledgments
謝辞

Thanks in particular to the following for their feedback to improve this article: Michal Mocny, Jay Miller, “Alexey,” “praetorian20,” Francisco Lopes, “Neil,” Daryle Walker.

この記事をより良くするための以下の各位からのフィードバックに対し、特別に感謝する:Michal Mocny, Jay Miller, “Alexey,” “praetorian20,” Francisco Lopes, “Neil,” Daryle Walker

Exceptional C++―47のクイズ形式によるプログラム問題と解法 (C++ in‐Depth Series)

Exceptional C++―47のクイズ形式によるプログラム問題と解法 (C++ in‐Depth Series)

  • 作者: ハーブサッター,浜田光之,Harb Sutter,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/11
  • メディア: 単行本
  • 購入: 9人 クリック: 134回
  • この商品を含むブログ (62件) を見る

Exceptional C++ Style―40のクイズ形式によるプログラム問題と解法=スタイル編 (C++ in‐Depth Series)

Exceptional C++ Style―40のクイズ形式によるプログラム問題と解法=スタイル編 (C++ in‐Depth Series)

  • 作者: ハーブサッター,浜田光之,Herb Sutter,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2006/09
  • メディア: 単行本
  • 購入: 3人 クリック: 32回
  • この商品を含むブログ (29件) を見る

More Exceptional C++ さらに40のクイズ形式によるプログラム問題と解法 (C++ In‐Depth Series)

More Exceptional C++ さらに40のクイズ形式によるプログラム問題と解法 (C++ In‐Depth Series)

  • 作者: ハーブサッター,Herb Sutter,浜田光之,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2008/11/05
  • メディア: 単行本(ソフトカバー)
  • 購入: 2人 クリック: 32回
  • この商品を含むブログ (19件) を見る

複数のターミナル間で bash のヒストリを共有する方法

Guake とか Terminator とか iTerm とか Console2 とかでタブを開きまくっていると、あっちのタブで入力したコマンドがこっちのタブにはヒストリとして出てこない!ムキーっってなりますね。特に超絶かっこいいワンライナーを書いた時にそれを再利用するためにどのタブで打ったか探しまわったりしている時には、ハイテクなんだかローテクなんだかよくわからなくて惨めな気持ちになりますね。

だいぶ前に、この問題の解決を試みようとしたときはなぜか全然うまく行かなくて挫折した記憶があるのですが、今日改めてぐぐってみたら一発で解決しました。

$ export PROMPT_COMMAND='history -a; history -r'

これだけです。
これを ~/.bashrc の片隅にでも忍ばせておくだけで幸せになれること請け合いです。


以下、ちょっと解説。

まず、bash の組込み変数(シェル変数)である PROMPT_COMMAND に値を設定しておくと、bash はプロンプトを表示する直前に毎回そのコマンドを実行してくれるようです。

そこに history -a と history -r を実行するように指定しています。

history -a はそのセッションで直前に実行したコマンドをヒストリ保存ファイルに追加するためのコマンドです。
history -r はヒストリ保存ファイルに保存されている内容をロードするためのコマンドです。

ですので、あるセッションで打ったコマンドがリアルタイムにすべてのセッションのヒストリに反映されるわけではありませんが、大抵の場合は意識せずともコマンド履歴がマージされながら更新されていくことになるので問題ないでしょう。

入門bash 第3版

入門bash 第3版


bashクックブック

bashクックブック

Herb Sutter さんによる GotW C++14 版 勝手訳

Herb Sutter さんがブログ Sutter's Mill で GotW (Guru of the Week) の更新を始められましたね。
とても面白い連載なので、一気読みしてしまった挙句、ついカッとなって勢い余って日本語に訳してみました。

まずは「これから更新始めるよ~」という感じの前振りの記事から。
原文にキャッチアップするように GotW の翻訳を順次アップして行きたいと思います。

原文では、問題提起の記事を掲載してしばらくたってから解答の記事を載せていますが、私の翻訳はそんな周りくどいことはせずに解答の記事を直接翻訳して載せようと思います。
また、翻訳にあたっては、原文の英語もそのまま載せて、日本語訳は引用の形式を使って、パラグラフなどの単位で対訳のように載せていきます。

原文著者(Herb Sutter 氏)の許可は得ていませんし、私の英訳がヒドいクオリティである(用語の統一がとれていないとか、誤訳が含まれているとか)かもしれませんのでそこのところはご理解いただければと思います。



原文:http://herbsutter.com/2013/05/04/guru-of-the-week-and-the-exceptional-c-series/

Guru of the Week and the Exceptional C++ Series

今週の Guru(Guru of the Week)と Exceptional C++ シリーズ

2013-05-04 by Herb Sutter

It’s time for me to pick up Guru of the Week (GotW) again in earnest, as part of work on revising my three Exceptional C++ books for today’s C++. Most Exceptional C++ Items are enhanced versions of GotW issues, after all, so the simplest and best place to start is with GotW. It’s also much easier to write (and read) one short piece at a time.

私の三冊の Exceptional C++ 本を今日の C++ 向けに改訂する仕事の一部として、Guru of the Week (GotW) を再び真面目に取り上げる時が来ました。Exceptional C++ のほとんどの項目は GotW の改良版であり、結局のところ GotW から始めるのが最もシンプルでありベストです。一度に少しずつ書くほうが楽ということもありますし、きっと読む方のみなさんもその方が楽なことでしょう。

Last spring I wrote a few GotWs, but life got busy with the Standard C++ Foundation, isocpp.org, and C++14. I was also trying to figure out what reasonable tools to use to write new Items, since I wanted to publish the same Item on this blog and then in e-book and dead tree editions, all with a single source while maintaining a pleasing format. I’ve found a provisional promising tool (Word!) and format for that I’ll try out for now, and you’ll see it in the next GotW issue to be posted soon.

昨年の春、私はいくつかの GotW を書きましたが、Standard C++ Foundation や isocpp.org、C++14 で忙しくなってしまいました。また、私は新しい GotW の項目を書くのに適したツールはないかと探していました。項目を一度書いたら、このブログに載せるだけでなく同じものを電子書籍と紙の書籍として出版したいと思っていて、しかもメンテが楽なフォーマットが望ましいのですが、暫定でたどり着いたのはとても有望なツール(Word!)です。フォーマットは今試してみているところです。もうすぐ次の GotW の投稿をお目にかけることができるでしょう。

But a major issue was figuring out the right balance between updating existing GotW issues and writing new ones.

しかし大きな問題は、既存のGotWを更新するのと新しいものを書くのとのちょうどいいバランスを見つけることです。

Here’s where I landed…

私がたどり着いたのは…

First, I’ve decided to keep and revise nearly all of my existing Items.

まず、ほとんどすべての既存の項目を残し、更新することに決めました。

This is not an obvious choice: As a counterexample, some authors have decided to not revise their existing books, but to write new books about C++11, for various reasons including that they expect the advice in the earlier books is still current. I think the latter is partly true, because of course the topics are still current and the code still compiles – C++11 has a great backward compatibility story with C++98.

これは明白な選択ではないかもしれません。反例として、既存の本を書きなおすのではなく、既存の本の内容がいまだに古くなっていないなどの理由で C++11 についての新しい本を書き直すと決めた著者がいるとしましょう。既存の本の内容がまだ古くなっていないというのは部分的に真実です。取り上げているトピックは当然古くなっていませんし、コードも未だにコンパイルできます。C++11 は C++98 に対して素晴らしい後方互換性を持っています。

However, when I looked through my own articles and Items, every single one I looked at had two qualities:

しかしながら、私の記事と GotW の項目をひと通り見なおしてみたところ、それらは 2 つのクオリティを持っているように見えました。

  • The topic was still current and useful, so it should still be covered. (With very rare exceptions like material discussing the now-removed export template feature.)

トピックはまだ古くなっておらず有用なので、記事や項目の一つとしてカバーされてしかるべきもの。(とてもレアな例外として、現時点で削除されている export テンプレート機能に関する議論のようなものもあります)

  • The code and discussion were addressed with C++98-era advice that is now dated and/or incomplete.

コードや議論が C++98 時代のもので、古くなっていたり不完全になっているもの

For example, nearly every GotW’s code should just naturally use auto and { } initialization. Most should use or actively discuss move semantics, lambdas, and other C++11 features. And it’s hard to write about existing features like virtual function overriding (as in GotW #5) without feeling something important is missing unless there’s also discussion of the way C++ has extended the existing feature, such as with override and final.

たとえば、ほとんどすべての GotW のコードは auto と {} による初期化を使うべきですし、ほとんどのものはムーブセマンティクスやラムダなどの C++11 の機能を使うか少なくとも積極的に検討すべきです。そして 仮想関数のオーバーライドのような機能(GotW#5で取り上げられています)は、override や final といった C++の既存機能に対する拡張について触れなければ、何か大事なものを忘れているという違和感なしに書くことは難しいでしょう。

Second, I’ve decided not to target C++11 – rather, I’m going to write for C++14. Why would I do that, when C++ compilers [preemptive snarky remark: including my own team’s] are still catching up to C++11? For several good reasons:

二つめに、C++11 を対象にせず、C++14 を対象にすることに決めました。なぜそうするか。C++ コンパイラは [プリエンプティブでウザい備考:私のチームのも含め] 、いまだに C++11 に追いつこうとしてる段階なのに?いくつかの理由があります:

  • C++14 is going to be current C++ soon. As of April, it’s now feature-complete, and the detailed technical specification should be frozen this fall or winter (leaving time for ISO ballots and “’14” publication). Compilers and libraries are already aggressively implementing it. I wouldn’t be surprised if we had multiple fully-conforming C++14 implementations by the end of next year.

C++14 は間も無く、"カレント" の C++ になります。4 月の時点で、機能的には全て決定していて、詳細な技術仕様がこの秋か冬には確定します(ISO の投票と “’14” の発行に向け、出発です)。コンパイラとライブラリはすでに意欲的に C++14 を実装しています。来年の末には C++14 完全準拠の実装が複数あっても驚くに値しないでしょう。

  • C++14 is a small delta, a minor release aimed mainly at “completing C++11.” And it does complete C++11 well, to the point where as an author I really want to teach the complete story. I want to teach the complete “avoid writing new and delete” guidance that C++14 make_unique fully enables so that I can stop mumbling “except when you create a unique_ptr” as a special case. I want to write generic lambdas with C++14’s terse auto parameters that makes lambdas shorter to write and more flexible, and stop repeating parameter type names. I want to use C++14 move-capture in lambdas that makes them complete, and not feel obliged to talk about artificially putting objects on the heap and capturing shared_ptrs to them by value as a workaround for lack of move capture. And, in a few places where appropriate, I want to be free to use a few smaller C++14 tidbits like optional that can affect interface design guidance now that they’re in the draft standard.

C++14 は小さな差分であり、主に C++11 を完全なものにすることを意図したマイナーリリースです。そしてC++14 は本当に C++11 を完全なものにしますし、私も著者という立場から完全なものを伝えたいと思います。私は "new と deleteを書くことを避ける" ガイダンスを完全な形でお伝えしたいと思っていますが、それは C++14 の make_unique によって可能となります。make_unique のおかげで、「特殊なケースとして "unique_ptrを作る時は除外"」といってモゴモゴするのをやめることができるのです。私はジェネリックなラムダを、C++14 の auto を使って書きたいです。それによってラムダを短く書くこともできますし、より柔軟になり、パラメータの型名を何度も書くのをやめることができます。私はラムダにおいて C++14 のムーブキャプチャを使いたいです。それによりラムダは完全なものになりますし、ムーブキャプチャが無いことに対するワークアラウンドとしてオブジェクトをヒープに突っ込んでそれへのポインタを shared_ptr でキャプチャすることについて語らなくてはならないという気持ちからも解放されるわけです。そして、optional のような、小さいけれどインターフェイスデザインのガイダンスに影響を及ぼすようなすでに C++14 のドラフト入りしているいくつかのものを、それにふさわしいいくつかの場所では自由に使いたいです。

In addition, I’ve found that C++11/14 is changing my coding style, including my basic variable declaration style. I now think auto should be used consistently to declare local variables, even when you want to commit to a specific type(!) – this certainly surprised me, and likely will surprise you too, so I’ll cover that this year in a GotW and a recorded talk, no later than at C++ and Beyond later this year and possibly sooner.

くわえて、C++11/14は私のコーディングスタイルを変えたことに気づきました。その中には基本的な変数の宣言のスタイルも含まれます。私は今ではローカル変数を宣言するところでは一貫してautoを使うべきだと考えるようになりました。特定の型に確定したいときであってもです!これは特に私自身を驚かせました。あなたもおそらく驚くことになるでしょう。それで私はこの話題について今年中に GotW とトークの録音でカバーしようと思います。今年後半の C++ and Beyond より遅くはならないと思います。可能ならすぐにでもと思っています。

I’ve converged on the above by updating the first dozen Exceptional C++ Items (in GotW order), trying out alternatives and seeing how well each one worked out. Those first dozen Items are now done and I’m pleased with the result, showing off auto and move and generic lambdas and mutexes/atomics and the new meanings of const and mutable and everything else, most of their code tested against various of the latest compilers, their advice updated to be current with current C++. And in every single GotW, no matter how short, it just felt right to:

Exceptional C++ の最初の1ダースの項目を(GotW の順で)更新して、他のアイディアも試してそれがうまくいくかどうかを見ながら、上記の結論に収束しました。その最初の1ダースの項目は完了して、私はその結果に満足しています。auto やムーブ、ジェネリック ラムダ、ミューテックスとアトミック、const や mutable の新しい意味などをご覧に入れます。ほとんどのコードは複数の最新のコンパイラでテストしました。アドバイスは最新の C++ に合わせて最新になるように更新されました。すべての GotW ひとつひとつにおいては、それがどんなに短くても、以下のことが正しいと感じました:

  • keep the topic, because each topic is still as relevant and useful as ever;

トピックを維持する。なぜならすべてのトピックは未だ現役でありこれまでどおり有用;

  • revise the C++98 code and advice, because in every case both the code examples and the discussion was dated and/or incomplete, usually both; and

C++98 のコードとアドバイスは書きなおされる。なぜならすべてのケースにおいて、コード例と議論が古くなっているか不完全となっている(たいていは両方);そして

  • skip C++11 to write directly for the complete story in C++14 without apology, because it let me avoid digressions for workarounds not needed in C++14, which made the text cleaner and simpler.

特に断りなく C++11 をスキップして C++14 で書く。なぜなら C++14 を使うことで本題から外れたワークアラウンドを避けることができ、本文がより明確でよりシンプルになる。

As I’ve revised Items, I’ve found that some updates are small but pervasive, such as using auto. Others are extensive, with entire subsections completely rewritten, thrown out as no longer relevant, or newly added to cover essential new sides of the story in modern C++. For example, GotW #6 about const-correctness is now a two-parter, covering the new meanings of const and mutable. Watch for it soon.

GotW の項目を書き直してみて、いくつかの変更は、例えば auto を使うことのように、小さいけれども広範囲にわたっていることに気が付きました。他にも、大規模なもの、サブセクション全体を完全に書きなおすようなもの、もはや今日的な意味を持たないので捨て去られるもの、モダンな C++ において必須の新たな側面をカバーするために追加されたものがあります。たとえば、const 正当性について書かれた GotW #6 は const と mutable の新しい意味をカバーするために 2 部構成になりました。乞うご期待。

A word about numbering and sequence: My plan is to update and post most GotWs in numerical order starting with GotW #1, but every so often we’ll jump forward to new high numbers (starting with #89) as I create ones that weren’t originally a GotW – a Sutter’s Mill magazine article that wasn’t originally published as a GotW, or a brand-new C++14 topic. So for example you might see a sequence like “… 23, 24, 91, 25, 26, …”. All GotWs will have substantial new material, but the newly minted high numbers will be entirely on brand-new topics that didn’t arise in C++98 or just weren’t covered in GotW form before. (The handful of GotWs I wrote last year will be renumbered as they’re folded into the original series, either as updates or with new numbers in the original sequence if they’re on completely new topics. )

番号の付け方と順番について:私のプランは、#1 から始めて番号順にほとんどの GotW を更新していこうとしています。でもたまに既存の GotW にはなかったような新しい大きい番号(#89 から始まります)にジャンプして、GotW としては元々発行されていなかったような Sutter's Mill マガジンの記事や完全に新しい C++14 のトピックを載せます。なので、読者はたとえば "… 23, 24, 91, 25, 26, …" のような順番で記事を見ることになるでしょう。すべての GotW は充実した新しい内容となりますが、その新しく付け加えられた大きな番号の記事は C++98 では書かれなかったか GotW の形式では過去にカバーされなかったような全く新しいトピックになります。(昨年書いた一握りの GotW は、オリジナルのシリーズの中に違う番号で組み込まれるか、もしそれが完全に新しいトピックなら新しい番号で追加されます。)

I’ll start posting fresh C++11/14 GotWs in the next few days. As usual, I’ll first post a problem by itself to invite discussion about possible solutions, then after there’s been time for comments I’ll post my own solution and the next problem.

近日中に、新鮮な C++11/14 の GotW の投稿を開始します。まず問題を投稿して、それについての議論や解答案を喚起します。そのあとでしばらくコメントのための時間をおいてから私の解答を投稿し、次の問題に移ろうと思っています。


It’s kind of exciting to write “GotW14” – today’s C++ really does feel like a fresh new language.

"GotW14" を書くのはエキサイティングです。今日の C++ は本当に新鮮な新しい言語のような気がします。

I hope you enjoy them as much as I enjoy writing them.

私が書くのを楽しむのと同じくらい、みなさんも楽しんでいただけたらと思います。

Exceptional C++―47のクイズ形式によるプログラム問題と解法 (C++ in‐Depth Series)

Exceptional C++―47のクイズ形式によるプログラム問題と解法 (C++ in‐Depth Series)

  • 作者: ハーブサッター,浜田光之,Harb Sutter,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/11
  • メディア: 単行本
  • 購入: 9人 クリック: 134回
  • この商品を含むブログ (62件) を見る

Exceptional C++ Style―40のクイズ形式によるプログラム問題と解法=スタイル編 (C++ in‐Depth Series)

Exceptional C++ Style―40のクイズ形式によるプログラム問題と解法=スタイル編 (C++ in‐Depth Series)

  • 作者: ハーブサッター,浜田光之,Herb Sutter,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2006/09
  • メディア: 単行本
  • 購入: 3人 クリック: 32回
  • この商品を含むブログ (29件) を見る

More Exceptional C++ さらに40のクイズ形式によるプログラム問題と解法 (C++ In‐Depth Series)

More Exceptional C++ さらに40のクイズ形式によるプログラム問題と解法 (C++ In‐Depth Series)

  • 作者: ハーブサッター,Herb Sutter,浜田光之,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2008/11/05
  • メディア: 単行本(ソフトカバー)
  • 購入: 2人 クリック: 32回
  • この商品を含むブログ (19件) を見る

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)


Efficient C++パフォーマンスプログラミングテクニック

Efficient C++パフォーマンスプログラミングテクニック

  • 作者: ダブブルカ,デビットメイヒュ,浜田光之,Dov Bulka,David Mayhew,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/07
  • メディア: 単行本
  • 購入: 9人 クリック: 149回
  • この商品を含むブログ (31件) を見る

2つの Zip ファイルの中に含まれるファイルの差分(diff)を直接調べる方法

自分用メモ。

a.zip と b.zip があって、それぞれ x というファイルが含まれているとします。
a.zip の中の x と b.zip の中の x を比較したい場合、以下のようなワンライナーで比較することができます。

$ diff <(unzip -p a.zip x) <(unzip -p b.zip x)

もちろん、zip ファイルはファイル名だけじゃなくてディレクトリもあわせてパスとして指定することもできますし、zip の中のファイルも dir/to/x のように書けばzip内のディレクトリを指定できます。

< と ( の間に空白を開けるとエラーになりますので要注意。

また、zip 以外にも他の圧縮方式でもおそらく同じようなことができると思います。
unzip コマンドは ーp で標準出力にファイルを出力してくれます。他の圧縮方式用のコマンドでも同じようなオプションがあると思います。


このようにすると、いちいちテンポラリディレクトリを作って展開してから比較とかしなくてよいので気軽に比較できますし、後片付けしなくてもよいのですっきりですね。

echo コマンドで -e って表示させようとしてハマった話(と解決策)

最近 bash の complete コマンド(自動補完)がプチマイブームなので、自作のスクリプトのための補完とかをシコシコ作成しています。
そのうち、覚えたこととかをまとめてブログに書こうと目論んでいるところです。

で、例によって complete 用の関数とかを作ってる途中ですごく基本的なことでハマったのでここにメモしておきます。

それはタイトルにもあるとおり、echo コマンドを使って -e と表示させたかったのですが、-e は echo のオプション(エスケープシーケンス有効化)として解釈されてしまうので、

$ echo -e

を実行しても実際には何も表示されないという罠があります。

とりあえず思いつきで

$ echo -- -e

を試してみたのですが、これは効果なし。
echo のマニュアルをみても -- は存在しないようです。

仕方がないので

echo -n -
echo e

と2回にわけて実行して難を逃れたのですが、どうにもダサいですね。

ぐぐってみるにも -e って検索しづらい。。。

どうにか見つけた我らが StackOverflow のページでは、
bash - echo "-e" doesn't print anything - Stack Overflow

printf コマンドを使用していたり、あえてエスケープシーケンスを使って表示させてみたり、POSIXLY_CORRECT=1 という環境変数を設定してみたり、-e の前にゴミをつけてそれをパイプで sed に渡して消すっていう力技まで登場したりしていて、世界中でみんなが困っているんだなぁということがわかってなんかほっこりしました。

coreutils が使えるなら printf を使って表示するのがスマートなんではないでしょうか。


入門bash 第3版

入門bash 第3版


UNIXシェルスクリプトコマンドブック 第2版

UNIXシェルスクリプトコマンドブック 第2版


bashクックブック

bashクックブック


bash Manual&Reference

bash Manual&Reference

Ubuntu 12.04 (amd64) で IDA Pro を実行する方法

IDA Pro というリバースエンジニアリング用のツールがありますが、Windows 版、Linux 版、Mac 版が用意されています。

現在の仕事の開発環境は Linux なので Linux 版をダウンロードします。

特にインストールとかはしなくてもパッケージを展開したらすぐに実行できるのですが、Ubuntu 12.04 の 64bit バージョンではいくつかパッケージが足りない(というか IDA Pro から 32bit 版のライブラリが要求される)のでインストールする必要があります。

まずは普通に起動しようとすると、

$ ./idaq
./idaq: error while loading shared libraries: libgthread-2.0.so.0: cannot open shared object file: No such file or directory

こんな感じのエラーになると思います。
この libgthread-2.0.so.0 というファイルがシステムにインストールされていないので、それをシステムにインストールする必要があります。
このファイルがどのパッケージに含まれているかを dpkg コマンドで調べます。

$ dpkg -S libgthread-2.0.so.0
libglib2.0-0: /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.3200.3
libglib2.0-0: /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0

一番左のカラムに書かれているのがパッケージ名です。この例では libglib2.0-0 というパッケージに含まれているようです。

ではインストールしてみましょう。

$ sudo apt-get install libglib2.0-0
Reading package lists... Done
Building dependency tree       
Reading state information... Done
libglib2.0-0 is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

おや、すでにインストールされているようですね。

32ビット版のパッケージをインストールする必要があるのでした。

パッケージ名の後ろに :i386 を付与します。

$ sudo apt-get install libglib2.0-0:i386

今度はインストールできました。

では再び IDA Pro を実行してみましょう。

$ ./idaq
./idaq: error while loading shared libraries: libfreetype.so.6: cannot open shared object file: No such file or directory

今度はまた別のライブラリが見つからないと言っています。

いったいいくつのライブラリが見つからないのか、ldd コマンドでちょっと見てみましょう。

$ ldd idaq | grep 'not found'
	libfreetype.so.6 => not found
	libSM.so.6 => not found
	libICE.so.6 => not found
	libXrender.so.1 => not found
	libfontconfig.so.1 => not found
	libXext.so.6 => not found
	libX11.so.6 => not found

それぞれのライブラリについて、dpkg でパッケージを探して i386 版をインストールする必要があります。

$ ldd idaq | \grep 'not found' | awk '{ print $1 }' | xargs dpkg -S | awk '{ print $1 "i386" }' | sort | uniq 

このワンライナーを実行して表示されるパッケージをすべてインストールしましょう。

インストールまで一括でやっちゃいたい猛者はこちらをどうぞ:

$ ldd idaq | \grep 'not found' | awk '{ print $1 }' | xargs dpkg -S | awk '{ print $1 "i386" }' | sort | uniq | xargs sudo apt-get install -y

インストールが終わったら、

$ ./idaq

でようやく起動できました。


The Ida Pro Book: The Unofficial Guide to the World's Most Popular Disassembler

The Ida Pro Book: The Unofficial Guide to the World's Most Popular Disassembler


The IDA Pro Book: The Unofficial Guide to the World's Most Popular Disassembler

The IDA Pro Book: The Unofficial Guide to the World's Most Popular Disassembler


Reverse Engineering Code with IDA Pro

Reverse Engineering Code with IDA Pro


Disassembling Code: IDA Pro And SoftICE

Disassembling Code: IDA Pro And SoftICE

mruby on Tizen 2.1 beta

ゴールデンウイーク中に Tizen SDK 2.1 beta がリリースされたとのことでさっそく入手して mruby をビルドして動かしてみました。

build_config.rb に以下の内容を追加します。

といっても、前回の2.0の時からの変更点は rootstrap のディレクトリ名がちょっと変わったくらいです。

- TIZEN_GCC_I386_EMULATOR_BASE = "#{TIZEN_SDK}/platforms/tizen2.0/rootstraps/tizen-emulator-2.0.cpp"
+ TIZEN_GCC_I386_EMULATOR_BASE = "#{TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-emulator-2.1.native"

- TIZEN_GCC_ARM_DEVICE_BASE = "#{TIZEN_SDK}/platforms/tizen2.0/rootstraps/tizen-device-2.0.cpp"
+ TIZEN_GCC_ARM_DEVICE_BASE = "#{TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-device-2.1.native"

もしかしたらリンクするライブラリとかもちょっと変える必要があるかもしれませんが、実際にもっと本気で使うようになってから気にすることにします。

実行してみた結果:

(host)$ cd mruby
(host)$ ./minirake
(host)$ sdb -e root on
(host)$ sdb -e push build/tizen-x86/ /opt/apps/mruby/
(host)$ sdb -e shell
sh-4.1# /opt/apps/mruby/bin/mruby -e 'system "cat /etc/tizen-release"'
Tizen release 2.1.0 (Tizen)

2.0 のときからの変更点としては、 sdb root on コマンドが必要になったことくらいでしょうか。

今日から使える! 液晶マイコンボード付きmruby学習キット EAPL-Trainer mruby

今日から使える! 液晶マイコンボード付きmruby学習キット EAPL-Trainer mruby


Arduino イーサネットシールド

Arduino イーサネットシールド


Rubyプログラミング入門

Rubyプログラミング入門


たのしいRuby 第3版

たのしいRuby 第3版

grep で複数のパターンにマッチさせる方法

grep でたとえば abc もしくは def を含む行にマッチさせたい場合は

$ grep 'abc\|def' *

という感じにすれば OK ですが、ちょっと記号が多い気もします。

$ grep -e abc -e def *

というように -e オプションでマッチさせる条件を複数指定することができるようです。
これでも abc もしくは def を含む行にマッチします。

  • v オプションとの組み合わせでも使えます。
$ grep -v -e abc -e def *

これは、abc も def も含まない行にマッチします。

bash スクリプトで変数に値がセットされていない時だけデフォルト値を設定する方法

: ${X:="value"}

先頭に :(コロン)とそれに続いて空白を指定するのがミソ。
: は bash の組み込みコマンドで、渡された引数の展開だけを行うコマンドです。

これで X という変数が存在しないか存在していても値が null のとき、X に "value" という値が設定されます。