1

タイトルをより適切に言い換える方法がわかりません。

低レベルのコードを単純な関数の外に移動し、コードをクラス内に移動して、クラスがより複雑なものを処理できるようにしたいと考えています。
私はこれから行きたい:

void a(void) {
    [low level operation];
    //User typed simple operations
    [low level operation];
}

static void AClass::b() {
    register(a); //register(void (__cdecl *func)())
}

int main(void) {
    AClass::b();
    return 0;
}

に:

void a(void) {
    //[no low level operation]
    //User typed simple operations
    //[no low level operation]
}

static void AClass::b(void (*func)()) {
    auto funcA = [] (void (*func)()) -> void (*)() { 
        [that first low level operation]; 
        func(); //Which is: void a(void);
        [the second low level operation]; 
    };
    register(funcA(func));
}

int main(void) {
    AClass::b(&a);
    return 0;
}

現時点では、「< lambda >::operator ()' : function must return value」というエラーが表示されます-ポインターが原因です。どうすればこの問題を解決できますか? void を返すだけでは機能しません。ラムダへの参照によって引数(関数「func」)を渡すことも機能しません(この場合、ラムダはもはや単なる関数ではなくクラスです)-レジスタ(void(__cdecl *func)() )関数ラムダではない関数を変換できません。

私の問題を解決する方法はありますか?

4

2 に答える 2

1

ステートフル ラムダを関数ポインターに変換することはできません。

関数ポインターに変換できるのは、状態を持たないラムダのみです。

あなたの状態は、いくつかの裏口から滑り込む必要があります。glutDisplayFunc、ステートレス関数ポインターのみを取ります。変更することはできません。

何かを保存するためのバックドアを見つけることができれば、それを使用して任意のラムダを保存できます。この場合、glutDisplayFunc現在のウィンドウに関連付けられています。現在のウィンドウに状態を押し込んで、それがどれかを把握できる場所はありますか?

そのような を見つけたとしますvoid*。次に、単に a を割り当て、std::function<void()>そこに押し込み、次のラムダを登録します。

void AClass::b(void (*func)()) {
   auto funcA = [func] () { 
     [that first low level operation]; 
     func(); //Which is: void a(void);
     [the second low level operation]; 
   };
   registerPVoidSomewhere( new std::function<void()>( funcA ) );

   register([]() {
     void* pVoid = getPVoidFromWhereIHideItAbove();
     std::function<void()>* pFunc = reinterpret_cast<std::function<void()>*>( pVoid );
     if (pFunc) {
       (*pFunc)();
     };
   } );
}

現在のウィンドウが何であるかglutDisplayFuncを尋ねることができる場合、 が呼び出されるとコンテキストから呼び出されることに賭けています。glutおそらく、そのウィンドウにはユーザー定義の場所があるvoid*か、ウィンドウポインターからvoid*管理するグローバルマップを持つことができます(その2番目のケースでは、ウィンドウポインターから へのグローバルマップを持ち、std::function<void()>その厄介なものを取り除くこともできます鋳造)。

于 2013-03-29T01:49:17.610 に答える
0

2 つの問題があります。1 つは型に関するもので、もう 1 つはラムダを宣言して関数ポインターを返すが、実際には何も返さないというものです。

1 つ目は、テンプレートを使用して簡単に解決できます。

struct AClass
{
    template<typename Ft>
    static void b(Ft func)
    {
        auto funcA = [&func]()
        {
            // Do some stuff
            func();
            // Do some other stuff
        };
        some_register_function(funcA);
    }
};

ご覧のとおり、ラムダ宣言も変更しました。これは、あなたのバージョンでは実際にそれを呼び出し、引数として渡す関数ポインターも呼び出すため、これにより 2 番目の問題が解決されます

glutDisplayFunc純粋な C ライブラリの純粋な C 関数のように、実際に機能するかどうかはわかりません。ラムダや関数オブジェクトについては何も知りません。

于 2013-03-29T01:26:13.247 に答える