忍者ブログ

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

2025/05/18

ラムダ式ってなんぞ

vs2015のプロジェクトを立ち上げてすぐに目についた処理

プログラム
create_task([this, deferral]()
{
 m_deviceResources->Trim();
 // ここにコードを挿入します。
 deferral->Complete();
});

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

// シーン オブジェクトを更新します。
m_timer.Tick([&]()
{
 // TODO: これをアプリのコンテンツの更新関数で置き換えます。
 m_sceneRenderer->Update(m_timer);
 m_fpsTextRenderer->Update(m_timer);
});

むむ、これはラムダ式……
見たことはあるけど触ったことはない。
ということで軽く勉強。

・ラムダ式の定義
[] : ラムダキャプチャ(キャプチャは「&:参照」「=:コピー」で変数ごとの指定も可能)
() : 引数(ない場合省略可)
{} : 複合ステートメント(処理の実装部分)

・ラムダ式を使ってみる
 (※最後のカッコは「呼び出し」で、引数を渡します。)

プログラム
// 15を返す式( キャプチャ:無し 引数:無し 実装:return 15 )
int val15 = [] () { return 15; } ();
int val15 = [] { return 15; } (); // 引数部無しでも可

// 足し算( キャプチャ:無し 引数:int a, b; 実装:return a+b )
int a = 5, b = 7;
[] (int a, int b) { return a+b; } ( a, b );

// テスト関数
int testFunc()
{
 int a = 10, b = 2, c = 3;
 // aを20で上書きする( キャプチャ:参照 引数:なし 実装:a = 20)
 [&] { a = 20; } ();

 // ちなみにキャプチャがコピーのとき値の変更は不可能
 // この例だとたとえ変更できてもコピーされた値を書き換えただけなので
 // 結局反映されないんですけどね。
 //[=] { a = 20; } (); // コンパイルエラー
 
 return a*b - a*c;
}

ざっとこんな感じみたいです。

普通に関数書けるのであれば難しくないですね。
Func();
ラムダ();

むしろこれを引数にできたりするので実装を外に丸投げできますし
かなり素敵な機能……。

使うタイミングがあれば使っていこうかな、と思います。

拍手[0回]

PR

2015/08/09 プログラム Comment(0)

前方宣言 typedefの解決

やっと時間が出来始めたので制作開始。

さて、前方宣言の解決のメモ。


namespaceは普通にこう。

プログラム
// 前方宣言
namespace MySpace
{
 class MyClass;
};

// 使用例
void func(const MySpace::MyClass& object);

typedefは
プログラム
struct BaseClass
{
 int a, b c;
};
// typedef
typedef BaseClass MyClass;
という型があったとして、
MyClassを前方宣言したい場合

プログラム
// 前方宣言
struct BaseClass;
typedef BaseClass MyClass;

// 使用例
void func(const MyClass& object);
という風に
typedefする前の型も宣言すると使用できます。

基本メモ、と言うことで。

拍手[0回]

2015/07/15 プログラム Comment(0)

AndroidのTexture関係について

基本的には普通にgl関数を呼ぶだけでいいみたいですが、いちおうメモ。


まず生成について。
GLSurfaceView.Rendererの継承関数内であれば正常に生成できます。

次に破棄、これも
生成と同タイミングで可能です。


使用不可能なタイミングでgl関数を呼び出した場合は
[tag]libEGL
[text]call to OpenGL ES API with no current context (logged once per thread)
という使用不能である旨のログが残ります。
エラー落ちやブロッキングはないので安心ですね。

というわけでRenderer内部での処理にTexture生成、削除をしているなら
何の心配もなく行えます。
また、Activityが終了する際には解放する必要はありません。

exeの作成に慣れていると破棄時(ここではActivity.onDestroy呼び出し時)に
全要素を解放したくなりますが、ここはRendererの処理範囲外なので
例の使用不能呼び出しがログに残るだけです。
Textureは削除されていることを信じて祈りましょう。
コントロール出来ないのはちょっと気持ち悪いですが目をつむります。

さて、API内部で勝手に破棄してくれているので、再開時には
onSurfaceCreateで削除されたTextureを再生成する必要があるそうです。


以上を踏まえてタイトルなりゲーム部分なりを作る際には
プログラム
public abstract class Scene {

 public abstract void Init(); // 初期化. ロードはしない.
 public abstract void Step(); // 毎ループの更新処理.
 public abstract void Draw();// 毎ループの描画処理.
 public abstract void Destroy(); // 全メンバ変数の解放
 public abstract void DeleteTexture(); // Textureのみの破棄
 public abstract void LoadResources( resources ); // 全リソースのロード
 public abstract void LoadTexture( resources ); // Textureのみのロード
 public abstract void TouchEvent( event ); // Androidの入力処理

}
こんな感じです。とりあえずこれで1作品作ってみましたが
何ともしっくりこない作りですね。

今日も寒いなぁ…。
明日こそは外に出よう。

拍手[0回]

2015/01/25 プログラム Comment(0)

もう12日ですね


作業に没頭していると全然記事を書こうっていう気分にならないんですよねぇ。
日記はすぐ無くしますし……。

基本的に記録するのに向いてないのかもしれないなぁ。
まぁ忘備録もかねてますんで続けますけどね。


さて、今日はAndroidのプログラムをずっとしてました。しかもEclipceで。
Unityでやったほうが楽なんでしょうけど、一回やってみたかったんですよね。
javaとOpenGLによる開発です。

OpenGL触ったことあんまりなかったんで
取り敢えず3つほどのサイト調べつつ
Android公式リファレンス広げてふむふむと進めていきました。
慣れてない言語は手探り感がひどいですね。(笑)

***

まず嵌ったのがByteBufferの作成です。
ByteBuffer.allocate関数を呼んで救ったBufferはGLに使用できないんですね。
ByteBuffer.allocateDirect関数を使わねばなりません。
じゃないとエラーです。これはうっかりミス。

またglEnableClientStateで許可をだした場合その要素のnullは認められないようですね。
ログにエラーが出続けました。
nullチェックぐらいしてもよさそうなものですが……。
それともチェックした上でエラーを表示してるのかな?

glDisable、glDisableClientStateで無効にした場合はその要素が適用されなくなるのですが、
設定したBufferやObjectは参照し続けます。GCの対象外になりそうで怖いですね。
うっかり外し忘れると解放を忘れたオブジェクトが残りそうです。

***

とまぁこんな感覚でずっといじってました。
普段なら気にならないでしょうが、でっかいBufferを外し忘れると
占有サイズが大きくなりそうで怖いですね。まぁ滅多にない、ということなの…かな?


それにしてもホットミルクが美味しい季節ですね。
ではおやすみなさい。

拍手[0回]

2015/01/12 プログラム Comment(0)

ゆったりですが続くよ

本当にどうなってんのっていう寒さに体がついていきません。
運動しなきゃなぁ…。

皆さん突然の運動によるぎっくり腰には注意しましょうね。


はい、というわけで手作りアロケータ続きやっていきます。

メモリ確保のNew機能を実装しましょう。手順としては
1、メモリから空き要素を探す
2、空き要素を必要な分だけ使用中にする。
はい、これだけです。

んで、ここで問題です。ここでいうメモリはどこにあるんでしょうね。
この場合の正解は「どこにもない」です。作ってないですからね。
なのでまずメモリを作りましょう。

プログラム
namespace Allocater{
 
 class MemoryPool{
 private:
  void* memoryPool;
  uint memoryPoolSize;
  
 public:
  // ポインタのNULL初期化は忘れない事。
  MemoryPool() : memoryPool(NULL){}
  // 解放忘れてたら教えてもらう。
  ~MemoryPool()
  {
   if( memoryPool ){
    DEBUG_ERROR_PRINT("解放忘れ!");
   }
  }
  
  // メモリを確保する
  void Init(uint size)
  {
   // どこかで使っているかもしれないので解放しない
   // NULLのときだけ確保を許可する
   if( memoryPool == NULL ){
    memoryPoolSize = size;
    memoryPool = malloc(size);
   }
  };
  // メモリを解放する
  void Release()
  {
   if( memoryPool ){
    memoryPoolSize = 0;
    free( memoryPool );
    memoryPool = NULL;
   }
  }
 };
 
}/* Allocater */

おおざっぱにはこれだけです。
あ、DEBUG_ERROR_PRINT関数は適当です。
自作関数なりシステム関数なり使ってくださいね。

大きなメモリを確保するためだけに作ってます。
このクラスに空き要素を探してもらって、確保していくようにします。

あああストーブが消えた。
おやすみなさい。



前の記事

拍手[0回]

2014/12/18 プログラム Comment(0)

プロフィール
 
HN:
ユニ
性別:
男性
 
 
カテゴリー
 
 
 
最新記事
 
(03/09)
(10/27)
(08/09)
(07/15)
(06/02)