私のプログラムでは、メインライブラリに外部ライブラリ(GLFW)のヘッダーを含めました。このライブラリを使用するために必要なものはすべて、メインクラスで処理できますが、別のクラスで必要な2つの卑劣な小さなメソッドは例外です。
#include <GLFW/glfw3.h>
#include "graphics/Display.hpp"
int main()
{
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Adventum", nullptr, nullptr);
uint32_t extCount;
const char** extensions = glfwGetRequiredInstanceExtensions(&extCount);
Display* display = new Display();
//@formatter:off
auto terminate = [&](){glfwSetWindowShouldClose(window, true);};
auto surfaceCreation = [&](VkSurfaceKHR* surface){return (glfwCreateWindowSurface(display->instance, window, nullptr, surface));};
//@formatter:on
display->setTerminateFunction(terminate);
display->setSurfaceCreationFunction(surfaceCreation);
display->create(extensions, extCount);
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
}
display->destroy();
delete display;
glfwDestroyWindow(window);
glfwTerminate();
}
これは私のmain
関数です。私が必要とする2つの関数はglfwSetWindowShouldClose
とglfwCreateWindowSurface
で、どちらもmain
の変数への参照が必要であり、両方のクラスにヘッダーを含めることに加えて追加のハードルになります。ご覧のとおり、外部関数呼び出しを含む2つのラムダ関数(terminate
とsurfaceCreation
)を作成することでこれを解決しました。
私の質問は、これは経験豊富な開発者にとって目障りなものになるのでしょうか?これは粗雑で不要な回避策ですか? (私はそれが「意見に基づく」ことなしにこれを尋ねる方法を理解しようとしています。)
序文。この投稿の多くは、一般的に「C++ラムダをクロージャーとして使用して依存性と結合を減らす」ためのものです。したがって、そのようなコード全般に関するアドバイスが含まれています。ここのサンプルコードは、ここで与えられたすべてのアドバイスを満たしているようです。
この場合、C++ラムダをクロージャーとして使用することはまったく問題ありません。カップリングとヘッダーの依存関係を減らすため、これもお勧めします。
次の注意事項があります。これらは「知識に関する警告」です。つまり、最初に習得する必要があります。その後、恐れることなくC++ラムダを使用できます。
std::function
_として受け取ります(そして、おそらくそれを格納します)。1つのメンテナンスの警告。
実行順序の依存関係に関する経験則:
通常、設定を行うためのコードの順序は簡単です。依存関係は自然で明示的です。 (後の手順では、前の手順で作成した値とオブジェクトが必要になる可能性があります)
ただし、物を降ろす(破壊する)コードの順序は簡単ではありません。多くの場合、事態はプログラマーが意図した順序とは異なる順序で発生します。
これらの知識をコードサンプルに適用します。
まず、落ち着いてください。これはint main()
メソッドであることを忘れないでください。したがって、このメソッドで作成されるほとんどのローカル変数は、アプリケーションのランタイムである限り、実際には最後にalmostになります。ただし、main
メソッドの終了後に実行されるコード(静的オブジェクトのデストラクタなど)がある場合は、解放後使用の条件がトリガーされる可能性があります。
最初のラムダ(terminate
)では、ローカル変数window
は参照によってキャプチャされますであることを理解してください。 window
はポインターですが、参照によるキャプチャ([&](){...}
)を使用すると、このポインターを格納するローカル変数のアドレスがキャプチャされます。
ポインター値をコピーする場合は、copy-by-copy([=](){...}
)を使用するか、変数を名前で指定します([window](){...}
)。
ポインター値を保持する変数がデリゲートによってアクセスされることを意図している場合(デリゲートが別のオブジェクトを指すように更新する必要がない限り、ほとんどありません)、capture-by-referenceを使用します。
キャプチャーされるオブジェクトの存続期間を延長する必要がある場合は、C++スマートポインターのいずれかを使用します。通常は_shared_ptr
_または_weak_ptr
_;めったに_unique_ptr
_(注を参照)。これは、委任者が委任者よりも長く生きることを意図している場合に役立ちます。 (main
メソッドは、このサンプルコードのどのデリゲートよりも長く存続するため、ここではそうではありません。)
_unique_ptr
_のキャプチャに関する注意。 _unique_ptr
_を委任者からラムダ(「タスク/クロージャ」)に適切に転送するには、C++ 14が必要です。これはlambdaキャプチャ式を使用します。 (C++ 11ではなくC++ 14を自由に選択できないほとんどの人は、ほとんどの場合_shared_ptr
_または_weak_ptr
_にとどまることで問題を回避します。)