サクラ
を入力してから補完ウィンドウを出して サクラエディタ
を選ぶと、サクラサクラエディタ
みたいに補完されるのだけど、trunkをデバッグモードでコンパイルしたものがたまたまあるので試してみてもそんなことは起こらないから、何かの設定のせいなのか、よくわからないうちに直ったのか。■単語検索といえば昔のはてなダイアリーは豪快だった。サクラエディタも Trieとか接尾辞配列とかを導入したら、予め決めた単語境界に基づいて抽出した単語を登録済みキーワードと比較するのではなく、もっとアグレッシブに編集中のテキストから登録済みのキーワードを見つけ出せるのに。……とかいって俺には難しすぎるデータ構造だから最終更新: 2017-10-01T01:05+0900
https://svn.code.sf.net/p/sakura-editor/code/sakura -r 4196
BOOL KeySearchCore(...);
publicだが privateにできる。bool MiniMapCursorLineTip(...);
publicだが privateにできる。enum LID_SKH {...}
publicだが privateにできる。BOOL KeyWordHelpSearchDict(...);
publicだが privateにできる。bool ShowKeywordHelp(...);
publicDWORD m_dwTipTimer;
publicCTipWnd m_cTipWnd;
publicPOINT m_poTipCurPos;
publicだが privateにできる。CDicMgr m_cDicMgr;
publicだが privateにできる。class CEditView: public AsWithHelpTooltip<CEditView>
AsSelectable
みたいなのを想定した命名規則なんだけど。「public継承されたのもたまたま」
理想を追求する人は private 継承して public 部に using AsWithHelpTooltip::XXX
を並べるなり、継承ではなくコンポジションを選び一行だけの委譲関数を書くなりすると思う。というわけで、public 継承している現状に対応して AsWithHelpTooltip::OnTimer
と AsWithHelpTooltip::OnMouseMove
をクラス外部から隠す目的で public から protected に変更するのは間違い。public と private と protected が混在することになるという一事をもって即座に間違いだと気付くべきところ。
m_bInMenuLoop
が TRUE
にならないからなんだけど、なぜミニマップだけなのか。CTipWnd::ComputeWindowSize()
と CTipWnd::DrawTipText()
の中で DrawText()
の引数 pszWork
を new
してるけど、DrawTextはサイズを指定する引数も受け取るから _T('\0')
を埋める必要も new
する必要もないよね。DrawTipText()
というひとつの static 関数に反映されてる。CEditViewの問題は(ANSI版よりずっと改善したとはいえ)あらゆる機能がひとつのクラスに同居していることなので、publicが privateにできたからといってなんの安心材料にもなりはしない。試したかったのは1機能1クラスで CEditViewを拡張する方法。20091129p01とか20131130。新機能はただの余録。そういうのも簡単にできるよねっていうお試し。
個別機能クラスが結局は CEditViewのすべて(継承元である他の個別機能クラスを含む)に依存できそうなのがちょっと予想外だった。機能と機能の絡み合いがだんだんと窮まってきそう。privateデータメンバー(※)を狭い範囲に閉じ込めて守りやすいのだけが利点か。
※publicデータメンバーもメンバーアクセスを代行するだけのセッタゲッタもありませんよ。それを当然の前提にして privateデータメンバーに注目してる。
たまたま目についたひとつのメンバ変数 m_cTipWnd
を分離してやろうと思って初めてキーワードヘルプや補完機能をセットアップしてから、コードの絡み合いを解きほぐして再構成するのに一週間ちかくかかってる。これでは、とりあえず一か所に、とりあえず public
, friend
にしたくなるのもわかる。あえてクラスを分けてアクセスを制限して、その結果に頭を悩ませたい人間がいるだろうか。いやいるし必要なんだけど、結局自分の能力でできる範囲のやり方しかできない。この a.patch だって自信満々で晒してるわけではなくて、むしろクラス設計は迷いまくりで、AsWithHelpTooltip.GetLastHitKeywordDictionary()
なんて行き場のない妥協の産物である。正しい設計なんてのは与えられればそれ以外に考えられないくらい当たり前のものに思えるのに、自分でそこにたどり着くのは難しかったりする。高校数学の問題とかがそう。解法をチラ見すれば解ける。しかし独力ではなんのとっかかりも見つけられない。
最終更新: 2017-11-04T18:59+0900
クラスを書くときの理想として、コンストラクタでメンバーを初期化して以後は変更したくないというのがある。メンバーの状態は自身の行動の前提条件であり、そこが流動的ではあらゆるメソッドが事前に前提を確認してからでないと本題に入れなくなる。コンストラクタで準備の完了と条件の確認をすべて済ませておきたい。そこが動く、動いたなら、それはパラメータを変えた別のインスタンスに任せたい。
上で登場した AsWithHelpTooltip というオブジェクトは CTipWnd というオブジェクトをメンバーとして持っており、寿命を共にする。CTipWnd のサイズ(を始めとするその他諸々)を隠したいならポインタ(か参照)一択だが、そういう制約がないなら new CTipWnd の手間を避けて、AsWithHelpTooltip のサイズに CTipWnd のサイズを丸々含めるような持ち方をする。
初期化である。AsWithHelpTooltip とそのメンバーである CTipWnd は As~を継承する CEditView の初期化(ウィンドウ作成など)を待たないと初期化が完了しないので、As~のコンストラクタでは呼ばれるのが早すぎる。また、CEditView はコンストラクタとは別に Create という名前の初期化(リセット)関数を持っている。であれば As~にも Create という名前の初期化関数を生やして CEditView の Create から呼んでもらうというのが自然な流れ。As~はそれでいい。そのメンバーである CTipWnd にも Create の連鎖を波及させるべきだろうか。CTipWnd は小さな部品であり、そこそこ汎用性もある。そこに、外部の都合で、リセット関数という全く不要で全ての前提を覆す邪悪なメンバーを生やしてもいいものだろうか。
代入演算子を定義しようか。しかし代入は邪悪で避けるべきものだ。なにより外部のリソースを作成するときに使用したパラメータは、コンストラクタの中で使用するのみで以後は不要なので保存していない。代入なんかのためだけに余計な荷物をしょいこむなんてまっぴらごめんである。
ではやはりポインタだろうか。Create 関数が呼ばれるたびに new CTipWnd でメンバーのインスタンスを作り直そうか。こういうとき参照は使えない。参照はコンストラクタで初期化するしかできないし、初期化しなければいけない。そこが参照のポインタとは違う参照たる所以であるので不便でも不満でもない。しかしポインタには不満がある。ポインタは無効な状態(nullptr)を許容する所が参照とは違う点で、今回の As~と CTipWnd の関係ではそういう無効な状態の入り込む余地などないのだから、CTipWnd をポインタで持つというのは意図や前提の過不足のない表現として不適切で不満がある。
結局 As~の Create 関数の中でこうやって CTipWndを再作成したんですよ。
m_cTipWnd.~CTipWnd(); new(&m_cTipWnd) CTipWnd( G_AppInstance(), asView(this)->GetHwnd() );
代入なし、(CTipWndに)リセット関数なし、new なし、ポインタなしで満足してるんだけど、何かの本で読んだテクニックというわけではなくて、どんな落とし穴があるのか戦々恐々としてる。普通の new ですら使うのが怖くてできるだけ見えないように(STLを使ったり)するのに、placement new なんてとてもとても。
picojsonというパーサを読んでいます。分からないのは、以下に該当するコードです。deleteしていないのに、配置newしたオブジェクトがメモリリークしないのはなぜなのでしょうか。
inline value& value::operator= ( const value& x ) { if( this != &x ){ this->~value(); new (this) value(x); // thisの寿命はどうなる? } return *this; }
ほぼ同じ2行だ。そして picojson は知っているし信頼できるソースだ。だけど検索したら現在の picojson にはその2行がない。こういうことらしい。
make operator= safe when part of LHS is being assigned, as well as ex… · kazuho/picojson@96f6c81
exception-safe はわかる。破壊と構築がアトミックでないから、構築し損ねた荒れ地にさらにデストラクタが走る可能性がある。
でも when part of LHS is being assigned っていうのがわからない。さへんのいちぶぶんにだいにゅうされているとき?
c++ - Can I use placement new(this) in operator=? - Stack Overflow
ある回答者によれば『Exceptional C++』で言及されているらしい。もう一度読もうか。
その回答に補足して、継承とスライシングに関わる問題が placement new を使った手法にはあるとも指摘されている。picojson の主な理由もそれだったのかもしれないけど、よくわからん。
ある型の代入演算子の中で自身のデストラクタを呼ぶとき、それが仮想であるならば呼ばれるデストラクタは派生クラスのものであるかもしれず、placement new で新しいインスタンスで上書きするときに派生部分の初期化が行われない、と。そのようにコードを呼んだ側も呼ばれた側も意図するところは「ある型」部分に限った代入なので、仮想のデストラクタを呼んだのが間違い。
『[単行本(ソフトカバー)] Jaroslav Tulach【APIデザインの極意 Java/NetBeansアーキテクト探究ノート】 インプレス』を読んでその苦労を垣間見るけど、派生クラスは難しい。派生が可能なクラスを公開して、それを互換性を保ったまま改善するというのは、ほとんど不可能なのではないかと思えるほど。どれだけ注意を払っても余分なコードで対策しても、得られるのは「ソースコード上の」とか「バイナリの」とかいう条件付きの互換性なんだからやってられない。
『Exceptional C++』の項目41がそのものずばりでアンチイディオムとして取り上げており、すでに述べた2つ以外にもこれでもかこれでもかと否定の論拠を挙げていた。C++怖い。そして、「何かの本で読んだテクニックというわけではなくて」とか書いていたのは誰だっけ?
実際のところ、a.patch のケースでは例外安全性以外の問題はないと思うんだよね。Exceptional C++ のケースも picojson のケースも、継承を伴う代入演算子の話だし。問題があるのはたしかで万事うまくいく解決策もあるのに、あえて危険な手段をとったのが知識と思慮の不足ゆえなのは否定しようがないけど。
最終更新: 2017-09-01T03:21+0900
ダイヤテック マジェスタッチNキーロールオーバー カナなし 黒軸 FKBN108ML/NB
ダイヤテック
¥ 9,882
2009年からちょうど8年間くらい使ってる。最近ときどきあるキー(Nだったり Tだったり)が全く入力できなくなったり、Enterキーが2重に入力されたりしていて、ケーブルの断線を疑っていた。Enterキーが特に致命的で、日本語変換をしていて確定と同時にフォームが送信されることがたびたびあって、精神衛生上大いに問題だったので急いで新しいメインキーボードを調達したというわけ。
前々から赤軸とテンキーレスと漆塗り筐体に注目していて(20140103)、でも何枚もキーボードがあっても死蔵するだけだしと諦めていたので、渡りに船だったというのもある。
リニアで重たい黒軸の低反発バージョン。たしか前のキーボードを買ったときにはまだなかった。以前黒軸を「キータッチは重い。努力の必要なく底付きが避けられるほど。Realforceみたいなのをバチバチ叩かないための打ち方矯正キーボードではないか」と書いたのだけど、もはや矯正は完了したと思われるので低負荷の赤軸を使ってみたかった。(Realforceは PS/2接続が選べなかったり、Winキーが抜けていたりしてちょうどいいのがなかった。Winキーに関して今は違うとしても遅い)
日記を書いたりプログラミングをしてるときっていうのは案外考える時間が挟まることで適度に手が休んでいるのだけど、用意された原稿を PCに入力するみたいな単純で連続したタイピングではそれがなくて、手のひらが強ばって痛み出してくる。それが赤軸では軽減されるのではないかなと。なかなかそういう機会もないけどね。
黒軸でタイピングの調子が良いときはリズムがある。両手を上から下へ下ろす大きな動きがあって、その動きの間に両手の指がもにょもにょっと動く。ペチペチでもタタタンでもなく、もにょもにょっというのがポイント。そしてまた両手を持ち上げて、タイプする内容を確認して、一瞬の溜めで運指の計画が作成されるのを待ち、下ろす。
それほど深刻ではないスペースの問題。実際のところテンキーは有用。数字や日付の素早い入力が可能だし、マウスキー機能でマウスがない非常時でもポインタの操作が可能だし、Home/End/PgUp/PgDn/Del/Ins/↑/→/↓/←キーの代わりができるし、右下隅という狙いやすい位置にエンターキーがあるし、複数行コメント(/*...*/)を隣り合った2つのキーを連打することで開始できる。自分はこのように日々必ずテンキーを使っている。トラックボールを左手で操作しているので右手のマウスがテンキーに押しやられて遠くなりすぎるなんてこともない。テンキーは有用。だけどなくても困りはしない。どうしても欲しければテンキーだけを追加することができるが、たぶんそこまではしない。そういう存在。
フルキーボードから移ってきて、キー配置は標準的なものの意外にも打ちにくさを感じる。無意識にキーボード右端からの距離を測っていたようで、Home/End/PgDn/PgUpキーを押すときに指が右端から落ちそうになるのを恐れてためらってしまう。すぐ慣れるといいが。
前のキーボードはスタビライザーがちゃりちゃりうるさいと書いたが、これはそんなことがない。キーを外してみたらグリスが塗ってあった。考えることは同じか。
自分が普段いかにキーボードをチラ見していたかを知る。ちょっと打ちにくい。特にテンキーに頼っていた数字が。
キャップの重さでタイプの感じが変わるので、赤軸の標準の感触を確かめてから2色成形のキーキャップに変えるつもり。そちらは普通の天面印刷……印刷ではないけども。
キャップの高さが2色成形と付属のとで違うのを利用して、Altと Winキーだけ低めのキャップにしてる。どちらもうっかり触るとうっとうしいことになるキーなので間違えないように。
USB・Bluetooth兼用タイプならケーブルが脱着式で断線しても交換が可能なのになぜ? PS/2なら BIOSで設定したホットキーで PCの電源が入れられる。スタンバイ(S3)からでも休止状態(S4)からでも。シャットダウン状態からでもたぶんできたはず。いずれもマザーボードによる。
PS/2延長ケーブルと付属の PS/2-USB変換コネクタを通してキーボードをつないでるけど、キーボードと変換コネクタの間は普通にプラグアンドプレイしてる。PS/2なのに。
印刷との違いをどこに見出すか考えてしまう。漆は表面処理であって材質はプラスチックで変わらないし、素材を水分から守るという実用性が期待されているわけではないし、機械による印刷よりもデザインに制約がかかりそうだし、印刷にコピーされたとしても優る価値とは。画像だけを頼りに選ぶのは難しい。しぶき塗りと漆黒と悩んだ結果、金粉というマテリアルで選んでみたわけです。それを言ったら漆も特徴のあるマテリアルだけども、あんまり滑らかでわかりにくいよね。現代は安価な代用品がいくらでもある。
矢印キーの上の平面で右手を遊ばせたり指先でコツコツ叩いたりするのだけど、そこにあばたがあるのですね。わざわざ粗を探したりしないし、他の場所であれば、また、目であれば見過ごしていただろうけど、指先を欺くことはできないのだった。気になってひっかいてしまう。画竜点睛を欠く感じ。