/ 最近 .rdf 追記 編集 設定 本棚

log[20170908]ールチップ>a.patch | オブジトメンバーの持ち方初期化と再初期化参照とポインタ



20170908() [SakuraEditor]ールチップがおかしいよね選択した単語のヘルプがマウスカーソルのそばに出るそこじゃないよ■メニ>設定>ーワドヘルプ自動表示するを選ぶと(※この設定をソースコドで見つけてどこで設定できるのか探したiniには書き込まれない揮発性の設定みたいだ)選択しなくてもキャレト付近の単語の説明が出るんだけどポインタの先の単語じゃないんだよねポインタのそばに説明が出るのに……■ポインタがビーの上にないときには表示しない処理もあるんだよね表示するのはポインタではなくキャレトのそばの単語の説明なのに■誰かのこだわりの結果なのかなんなの普通じゃないね2.3.1.0で補完をすると例えば サクラ を入力してから補完ドウを出して サクラエ を選ぶと、サクラサクラエ みたいに補完されるのだけどtrunkをデバッグモドでコンパイルしたものがたまたまあるので試してみてもそんなことは起こらないから何かの設定のせいなのかよくわからないうちに直ったの■単語検索といえば昔のはてなダイアリーは豪快だったサクラエタも Trieとか接尾辞配列とかを導入したら予め決めた単語境界に基づいて抽出した単語を登録済みキーワドと比較するのではなくっとアグレッシブに編集中のテキトから登録済みのキーワドを見つけ出せるのに……とかいって俺には難しすぎるデータ構造だから他人事(ひとごと)だよ手を動かして理解する手もある?

最終更: 2017-10-01T01:05+0900

[SakuraEditor]ールチップ>a.patch

  • ースは https://svn.code.sf.net/p/sakura-editor/code/sakura -r 4196
  • +1007, -760増えた……
    • CEditView.h, CEditView.cpp, CEditView_Search.cpp, CEditView_Mouse.cpp に限定すると +28, -429圧倒的に減った(ァイルが2つ増えてるんだから多少はね)
    • 新ファイル(AsWithHelpTooltip.h, AsWithHelpTooltip.cpp)合計が 714
    • 目的は減量ではなく機能単位での CEditViewからの切り出しだから……
  • class CEditViewから消えたメンバー一覧
    • BOOL KeySearchCore(...); publicだが privateにできる
    • bool MiniMapCursorLineTip(...); publicだが privateにできる
    • enum LID_SKH {...} publicだが privateにできる
    • BOOL KeyWordHelpSearchDict(...); publicだが privateにできる
    • bool ShowKeywordHelp(...); public
    • DWORD m_dwTipTimer; public
    • CTipWnd m_cTipWnd; public
    • POINT m_poTipCurPos; publicだが privateにできる
    • CDicMgr m_cDicMgr; publicだが privateにできる
  • 代わりに継承元がひとつ増えた
    • class CEditView: public AsWithHelpTooltip<CEditView>
      • この名前ちっと微妙? AsSelectable みたいなのを想定した命名規則なんだけど
    • 基底クラスだけど仮想のデトラクタはないインターフェイスではないしpublic継承されたのもたまたまで想定される使い方では必要ないは
      • public継承されたのもたまたま

        理想を追求する人は private 継承して public 部に using AsWithHelpTooltip::XXX を並べるなり継承ではなくコンポジションを選び一行だけの委譲関数を書くなりすると思うというわけでpublic 継承している現状に対応して AsWithHelpTooltip::OnTimerAsWithHelpTooltip::OnMouseMove をクラス外部から隠す目的で public から protected に変更するのは間違いpublicprivateprotected が混在することになるという一事をもって即座に間違いだと気付くべきところ

      • protected 継承のことは知らないvirtual だとか菱形だとかの継承も難しすぎてわからない
  • [新機] メニ>設定>ーワドヘルプ自動表示する を有効にすると登録キーワドをポイトするだけでヘルプツールチップが出る
    • その際ツールチップの X座標は単語が始まる場所でY座標は注目している行の1.5行下
    • ャレトを動かしたときも同じ位置に出せるんだけどそこは互換性っていればポインタという定位置にヘルプが出るのも悪くないかもしれないし
  • [違う]ーの境界ギリギリでツールチップを表示したあとポインタをビーの外に持っていくとツールチップが消えないことが本家ではあったがそれがない
    • ミニマップ(これもビーの一種)のツールチップは必ず消えるんだけどどういう仕組みによるのかはわからなかった
    • ミニマップのツールチップはメインメニーが展開しているときにも出るこれは m_bInMenuLoopTRUE にならないからなんだけどなぜミニマップだけなの
  • [気付いた] CTipWnd::ComputeWindowSize()CTipWnd::DrawTipText() の中で DrawText() の引数 pszWorknew してるけどDrawTextはサイズを指定する引数も受け取るから _T('\0') を埋める必要も new する必要もないよね
    • というのが DrawTipText() というひとつの static 関数に反映されてる

 何がしたかったのか

CEditViewの問題は(ANSI版よりずっと改善したとはいえ)あらゆる機能がひとつのクラスに同居していることなのでpublicprivateにできたからといってなんの安心材料にもなりはしない試したかったのは1機能1クラスで CEditViewを拡張する方法。20091129p01とか20131130新機能はただの余録そういうのも簡単にできるよねっていうお試し

個別機能クラスが結局は CEditViewのすべて(継承元である他の個別機能クラスを含む)に依存できそうなのがちっと予想外だった機能と機能の絡み合いがだんだんと窮まってきそうprivateータメンバ()を狭い範囲に閉じ込めて守りやすいのだけが利点

publicータメンバーもメンバーアクセスを代行するだけのセッタゲッタもありませんよそれを当然の前提にして privateータメンバーに注目してる

 述懐

たまたま目についたひとつのメンバ変数 m_cTipWnd を分離してやろうと思って初めてキーワドヘルプや補完機能をセトアップしてからドの絡み合いを解きほぐして再構成するのに一週間ちかくかかってるこれではとりあえず一か所にとりあえず public, friend にしたくなるのもわかるあえてクラスを分けてアクセスを制限してその結果に頭を悩ませたい人間がいるだろういやいるし必要なんだけど結局自分の能力でできる範囲のやり方しかできないこの a.patchって自信満々で晒してるわけではなくてむしろクラス設計は迷いまくりで、AsWithHelpTooltip.GetLastHitKeywordDictionary() なんて行き場のない妥協の産物である正しい設計なんてのは与えられればそれ以外に考えられないくらい当たり前のものに思えるのに自分でそこにたどり着くのは難しかったりする高校数学の問題とかがそう解法をチラ見すれば解けるしかし独力ではなんのとっかかりも見つけられない

最終更: 2017-11-04T18:59+0900

[C++] オブジトメンバーの持ち方初期化と再初期化参照とポインタ

クラスを書くときの理想としてトラクタでメンバーを初期化して以後は変更したくないというのがあるメンバーの状態は自身の行動の前提条件でありそこが流動的ではあらゆるメソドが事前に前提を確認してからでないと本題に入れなくなるトラクタで準備の完了と条件の確認をすべて済ませておきたいそこが動く動いたならそれはパラメータを変えた別のイスタスに任せたい

上で登場した AsWithHelpTooltip というオブジトは CTipWnd というオブジトをメンバーとして持っており寿命を共にするCTipWnd のサイズ(を始めとするその他諸々)を隠したいならポインタ(か参照)一択だがそういう制約がないなら new CTipWnd の手間を避けてAsWithHelpTooltip のサイズに CTipWnd のサイズを丸々含めるような持ち方をする

初期化であるAsWithHelpTooltip とそのメンバーである CTipWndAs~を継承する CEditView の初期化(ドウ作成など)を待たないと初期化が完了しないのでAs~のコトラクタでは呼ばれるのが早すぎるまたCEditView はコトラクタとは別に Create という名前の初期化(リセ)関数を持っているであれば As~にも Create という名前の初期化関数を生やして CEditViewCreate から呼んでもらうというのが自然な流れ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 なんてとてもとても

 @2017-09-28 placement new より swap

picojsonというパーサを読んでいます。分からないのは以下に該当するコドです。deleteしていないのに配置newしたオブジトがメモリリークしないのはなぜなのでしょう

6
7
8
9
10
11
12
inline value& value::operator= ( const value& x ) {
    if( this != &x ){
        this->~value();
        new (this) value(x); // thisの寿命はどうなる?
    }
    return *this;
}
[C++]自壊と配置new自動的な開放? • C言語交流フーラム ~ mixC++

ほぼ同じ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 っていうのがわからないさへんのいちぶぶんにだいにゅうされているとき?

 @2017-10-30 placement new より swap ()

c++ - Can I use placement new(this) in operator=? - Stack Overflow

ある回答者によれExceptional C++で言及されているらしいもう一度読もう

その回答に補足して継承とスライシングに関わる問題が placement new を使った手法にはあるとも指摘されているpicojson の主な理由もそれだったのかもしれないけどよくわからん

ある型の代入演算子の中で自身のデトラクタを呼ぶときそれが仮想であるならば呼ばれるデトラクタは派生クラスのものであるかもしれずplacement new で新しいイスタスで上書きするときに派生部分の初期化が行われないそのようにコドを呼んだ側も呼ばれた側も意図するところ「ある型部分に限った代入なので仮想のデトラクタを呼んだのが間違い

[単行(ソトカバ] Jaroslav TulachAPIデザインの極意 Java/NetBeansーキテト探究ト】 インプを読んでその苦労を垣間見るけど派生クラスは難しい派生が可能なクラスを公開してそれを互換性を保ったまま改善するというのはほとんど不可能なのではないかと思えるほどどれだけ注意を払っても余分なコドで対策しても得られるの「ソースコド上の「バイナリのとかいう条件付きの互換性なんだからやってられない

 @2017-11-02 placement new より swap (続きの続)

Exceptional C++の項目41がそのものずばりでアンチイオムとして取り上げておりすでに述べた2つ以外にもこれでもかこれでもかと否定の論拠を挙げていたC++怖いそして「何かの本で読んだテクニックというわけではなくてとか書いていたのは誰だっけ?

実際のところa.patch のケースでは例外安全性以外の問題はないと思うんだよねExceptional C++ のケースも picojson のケースも継承を伴う代入演算子の話だし問題があるのはたしかで万事うまくいく解決策もあるのにあえて危険な手段をとったのが知識と思慮の不足ゆえなのは否定しようがないけど