【c++】 クラス内のメンバを部分的にアクセス許可する部分的なフレンド

今日のはちょっとネタっぽいですが、
c++ やってて、設計的にどうしても、一部分だけアクセスを許したいけど全体公開はしたくない、ってことはたまーにありますよね。

んで、最近よく使ってるのが以下のコード。

class MyClass
{
public:
	class ProcessAccessKey
	{
		friend class MyClass;
		friend class XXXX;
	private:
		ProcessAccessKey(){}
	};
	
public:
	void process( const ProcessAccessKey& key );
	
};


MyClass::ProcessAccessKey が生成できれば、MyClass::process() へのアクセスを許す感じです。
で、どうしてもアクセスが必要なクラスに対しては ProcessAccessKey にフレンド登録します。


一応これで friend を擬似的に部分的に適応することができます。

SublimeText2 プラグイン:セパレータ展開

2013/10/09 追記:不具合修正しました


プログラム上に出てくるよく出てくるコメント

//---------------------------------------

みたいなやつを展開するプラグインです。


ポイントはこんな感じ。

・複数種類から選べる
・特定の文字数までで展開をとめる
 (例えばエディタ上で80文字までしか展開しない、とか)
・連続で呼べる


解説

呼び出すとクイックパネルが表示されます。

f:id:edith_tky:20131007004945p:plain

ここから好きなセパレータを選んで Enter キーを押すと、
カーソルキーのところにセパレータが展開されます。

選択後、さっき選んだ選択肢が一番上にある状態でもう一度起動されます。
つまり Enter キーをすぐ押せば同じものがすぐ展開できます。

やめる場合は Esc キーでプラグインを停止できます。

特殊なコマンド

↑を見てもらえればわかりますが、アンドゥ・リドゥに対応してます。

セパレータ展開ルール

見てもらったほうが早いと思うのでまずはイメージを確認して下さい。

適応前
f:id:edith_tky:20131007004947p:plain

適応後
f:id:edith_tky:20131007004946p:plain


行頭からカーソルまでをインデントとして扱い、
カーソル行に "//-------------\n" を挿入し、
次の行でインデント分のテキストを挿入します。

エディタの縦線は80文字目のところに出るようになってるので
ちょうど80文字目までセパレータが展開されているのがわかります。

オプションについて

以下のオプションに対応しています。

f:id:edith_tky:20131007004948p:plain

separator_type

セパレータとして繰り返す文字列の配列がクイックパネルのリストになります。
指定がなければ [ "-", "=", "*", "/", "~" ] がデフォルトになります

separator_length

エディタ上で指定した文字数までセパレータを展開します。デフォルト80文字です。

既知の不具合

separator_type に複数バイトの文字列を与えるとうまく動かないです。
半角2文字までなら、現状でも大丈夫みたいです。

→ 2013/10/09 修正しました。

コメントが定義されていないファイル形式の場合には // が使われるようにしました。

→ 2013/10/09 修正しました。

マクロの可変長引数に対しての all_of, any_of, none_of アルゴリズム


最近 Boost.PP をすごく使うことが多いので
使ってる中で、欲しかったアルゴリズムを作ってみました。


マクロは個人的にはキライな方なんですが
Boost.PP くらい突き抜けるとアリだな、と思います。

#define  PP_VA_ALL_OF( mac, ... )  \
  BOOST_PP_EQUAL(  \
    BOOST_PP_SEQ_SIZE(  \
      BOOST_PP_SEQ_FILTER( PP_DETAIL_ALGORITHM_EXPAND, _,  \
        BOOST_PP_SEQ_FOR_EACH( PP_DETAIL_ALGORITHM_APPLY, mac, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
        )  \
      ),  \
      BOOST_PP_SEQ_SIZE( BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
    )

#define PP_VA_ANY_OF( mac, ... )  \
  BOOST_PP_BOOL(  \
    BOOST_PP_SEQ_SIZE(  \
      BOOST_PP_SEQ_FILTER( PP_DETAIL_ALGORITHM_EXPAND, _,  \
        BOOST_PP_SEQ_FOR_EACH( PP_DETAIL_ALGORITHM_APPLY, mac, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
        )  \
      )  \
    )

#define PP_VA_NONE_OF( mac, ... )  \
  BOOST_PP_NOT(  \
    BOOST_PP_BOOL(  \
      BOOST_PP_SEQ_SIZE(  \
        BOOST_PP_SEQ_FILTER( PP_DETAIL_ALGORITHM_EXPAND, _,  \
          BOOST_PP_SEQ_FOR_EACH( PP_DETAIL_ALGORITHM_APPLY, mac, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
          )  \
        )  \
      )  \
    )

#define PP_DETAIL_ALGORITHM_APPLY( r, data, elem )      ( data( elem ) )
#define PP_DETAIL_ALGORITHM_EXPAND( r, data, elem )      elem

#define ARGSa  boo,foo,bar
#define ARGSb  ,,,
#define ARGSc  boo,,bar

// 確認用コード                            // ↓出力
PP_VA_ALL_OF( BOOST_PP_IS_EMPTY, ARGSa );  // 0 
PP_VA_ALL_OF( BOOST_PP_IS_EMPTY, ARGSb );  // 1 
PP_VA_ALL_OF( BOOST_PP_IS_EMPTY, ARGSc );  // 0 
PP_VA_ANY_OF( BOOST_PP_IS_EMPTY, ARGSa );  // 0 
PP_VA_ANY_OF( BOOST_PP_IS_EMPTY, ARGSb );  // 1 
PP_VA_ANY_OF( BOOST_PP_IS_EMPTY, ARGSc );  // 1 
PP_VA_NONE_OF( BOOST_PP_IS_EMPTY, ARGSa ); // 1 
PP_VA_NONE_OF( BOOST_PP_IS_EMPTY, ARGSb ); // 0 
PP_VA_NONE_OF( BOOST_PP_IS_EMPTY, ARGSc ); // 0 


本当は、PP_VA_ANY_OF が欲しくて、


「可変長引数に空引数があると
 Boost.Concept でも使ってわかりやすいビルドエラーにしたい」


という感じで作りました。


マクロのエラーはテンプレのエラーよりも追いかけるのが大変なので…(^_^;)

SublimeText2 プラグイン:リピート展開プラグイン


単純な繰り返しを手打ちでコーディングするのはしんどいのでそのサポート機能を作りました。


起動すると以下のように入力パネルが表示されます。


説明としては、
"展開する文字列/展開数"
"展開する文字列/初期値、終了値、ステップ(省略時は1)"
のどちらかのフォーマットで入力すると、
その回数分、展開する文字列が展開されます。
また、展開時に文字列内の "##" を展開時の数値に置換して展開します。


わかりづらいと思うので、展開後のキャプチャを見てみてください。

上は、"##,/10"
下は、"typename T##, /5"
という感じで入力すると展開出来ます。


一応、現状はこんな感じでファイル単位での履歴を持てるようにしてます。
(最終的にはエディタで履歴を持てるようにしたい…ッ)



コードが長くなったので、見たい方はこちらでどうぞ。
https://github.com/edith-tky/sublimetext2_env/blob/master/User/RepeatInput.py

SublimeText2 プラグイン:ファイルを閉じたら左隣りのファイルをアクティブにする

※2013-07-28 不具合修正しました。詳細は下の方にて。


デフォルトだとファイルを閉じたあとに、
どのファイルにフォーカスが移っているのかがすごくわかりづらいため、


「ファイルを閉じたら左隣りのファイルをアクティブにする」


プラグインを作成しました。




以下が、そのコードです。

import sublime, sublime_plugin

class CloseViewToFocusLeftViewCommand(sublime_plugin.WindowCommand):
	def run(self):
		
		myWindow = sublime.active_window()
		myView = myWindow.active_view()
		
		myGroup, myIndex = myWindow.get_view_index( myView )
		
		sameGroupViews = []
		for view in myWindow.views():
			group, index = myWindow.get_view_index( view )
			
			if group == myGroup:
				while len(sameGroupViews) <= index: sameGroupViews.append(-1)
				sameGroupViews[index] = view
		
		nextIndex = myIndex - 1
		if nextIndex < 0:
			nextIndex = 0
		
		myWindow.run_command( "close_file" )
		myWindow.focus_view( sameGroupViews[nextIndex] )
		


たぶん、コピペしてもらえれば、使えると思います。

そのうち、PackageControl なんかに登録するのもやってみたいなー。


※2013-07-28 追記

閉じようとしているファイルが未保存の場合に、ダイアログの確認でキャンセルをすると、閉じてないのに左のタブにフォーカスが移ってしまう不具合修正。


修正部分は以下の通り。

		myWindow.run_command( "close_file" )
		myWindow.focus_view( sameGroupViews[nextIndex] )

  ↓↓↓

		myWindow.run_command( "close_file" )
		confirm = myWindow.get_view_index( myView )
		if confirm[0] < 0:
			myWindow.focus_view( sameGroupViews[nextIndex] )

秀丸からの SublimeText2 への機能移植計画

触ってる感じだとかなり基本機能のポテンシャルが高くイイ感じな SublimeText2 。

今まで使ってた秀丸からの便利機能移植を考えます。

とりあえず今まで使ってた機能を列挙してみる。

秀丸オリジナル

部分編集

 特定のスコープ内だけとかしかカーソルが移動できなくする機能
 ・関数内だけで全置換したいとか、検索したい
 ・ctrl+home, ctrl+end で、ファイルの先頭・終端じゃなく
  関数の先頭・終端に行ったり
 など、なかなかニクイ働きをする。
 

どの関数にいるか

 VisualStudio などの統合環境使ってたら普通にある
 カーソルがどの関数内にいるのかの把握。
 1画面に関数が収まらないことは、残念ながらザラにある。
 

追加コピー、ペースト

 複数行にまたがってカットしたいコードなどが意外とあるので便利。

タブ閉じたら左側をアクティブにする

 SublimeText2 は直前にアクティブだったタブに移動する。
 けど、タブ閉じた時に、どこにフォーカスが移ったか見失うことが多いので個人的には外せない。
 

独自マクロ拡張・キー割り当て

上下左右 ctrl+[hjkl] 化

 右手を←↓↑→キーまで持っていくのやだ。
 

簡易ハイライト

 目で検索するのやだ。
 
 しょうもない変数名ミスでビルドエラーでると凹むので、
 クラス名や変数名などを入力した時にハイライトさせて
 近所で実装した同名のものと同じか確認する。
  

インクルード通し

 ファイルを指定すれば、
 ソースコードに #include "パス/ファイル.h" が展開される機能。
 
 フォルダ構成など、自分よりもPCのほうが「素早く正確に」行える。
 

コメントセパレータ

 こんなやつを展開する機能

 //-------------------------------------

 
 毎回打ったりするのは面倒ですよね。
 
  

ネームスペース展開

 
 自分の閉じカッコミスがひどく、ビルドエラーもヒドいことになるので
 個人的には外せない機能。
 
 boo::foo と入力すれば

namespace boo { namespace foo {
	
}} // namespace boo::foo

 
 となる。無名ネームスペースも対応。
 ネームスペースなんて自分で書くもんじゃない。
 
 

グループ移動、グループ内タブフォーカス

 自分の任意のタブを表示したまま別グループで作業をしたいので
 タブのコントロールがしたい。
 

関数コメント展開

 //----------------
 /*! @brief  
   *  @param value : 
   */
  void func( int value );

 
 上記関数に対して、起動すれば、その上側のコメントを展開する機能
 引数とか戻り値もコメント側に対応される。

n 回リピート

input>typename T#/1..5
typename T1, typename T2, typename T3, typename T4, typename T5

 上記、"typename T#/1..5" と入力すれば
 1~5 までを # に展開する。
 
 c++ のテンプレートで
 自作タイプリスト作った時に非常に役に立ったw
 

ファイルリストから選択してタブ移動

 エディタ上で多くのファイルを同時に開くので、該当のファイルを探す手間が惜しい


今後の予定

 ひとまず、1つずつ環境構築をしていく予定~。
 ちまちまと準備中!

SublimeText2 に乗り換え中!

最近、自分の周りで「いいよー」と話題に上がっていた
SublimeText2 を試してみました。


最初に参考にしたのはこのへんのサイト↓

 ・”恋に落ちるエディタ”「Sublime Text」 完全入門ガイド!
 http://liginc.co.jp/designer/archives/6774

 ・NicoHack!第三回 おしゃれなテキストエディタSublime Textを使おう!
 http://ch.nicovideo.jp/tanzo/blomaga/ar152449



さすが「恋に落ちる」と銘打たれるだけあって、
すごくポテンシャルを感じるエディタですね。


個人的にヤバイと思ったのは
TextMate というエディタのハイライトと互換のある言語設定とテーマです。


これらがなにをしているかザックリいうと、

 言語設定 → ルールに沿ってテキストをパースして内部的な名前をつける
 テーマ  → その名前に対してカラーリング

という流れ。


言語設定はデフォルトで多くの言語をサポートしていてユーザは意識する必要はなく、
テーマについては、かなり多くのカラー設定が Web 上で入手することができます。



え?それだけ?という感じかもですが、

それだけじゃなくて…



スクリプトからその「パースしてつけられた名前」を取得できます!


例えば…、c++ だと、entity.function.c という名前で
スクリプトからアクセスすれば、
そのファイルの「関数リスト」が取得出来ます!



他にも、
「ネームスペースがいくつネストしていて、クラスの中のどの関数定義のなかにいる」
とかがだいたい分かりそうな感じだったりとかで…


スクリプトからイロイロできてしまいそうです!




自分のエディタ遍歴としては、
10年来「秀丸エディタ」を使用していて、
秀丸マクロを駆使してオレオレチューニングしてましたが
秀丸マクロの旧世代的というか、c 言語ベースの設計な使いづらさが嫌になってました。
(最後らへんは文字列処理するときは ruby スクリプトに投げて処理してたしw)


Vim を試してた時期もありましたが
こっちは使いこなす前に挫折…。よいエディタだったんですけどね…。



さて、肝心の SublimeText2 ですが、
初期状態だと、オレオレチューンの秀丸には残念ながら及ばないので
ちまちまセットアップしつつ、
最強の相棒になれるようにしようかなと画策してます。


スクリプトは python が使えるので
とりあえずその部分では既に秀丸を超えてますね!


軽く調べた感じでは、
欲しい機能がなかったりもするので、
メモがてら公開しとけば誰かの役に立つかなーと考えてます。