
C++/WinRT에서 직접 구현한 객체를 만들 때는 make<Impl>과 make_self<Impl> 중 하나를 쓴다. 먼저 Windows Runtime 프로젝션(projection)을 사용할지, 구현 객체에 접근할지에 따라 선택하면 된다.
여기서 Impl은 Windows Runtime 객체를 구현한 클래스다. IDL 파일에 선언된 객체라면 인스턴스 객체는 winrt::Namespace::implementation::ClassName, 팩터리 객체는 winrt::Namespace::factory_implementation::ClassName이다. IDL에 선언되지 않았다면 winrt::implements를 직접 상속한 클래스가 Impl이다.
make<Impl>은 구현 객체를 만든 뒤 Windows Runtime 프로젝션을 반환한다. Impl이 winrt::implements를 직접 상속했다면 프로젝션은 첫 번째로 구현한 인터페이스다. 프로젝션에 노출되지 않은 구현 객체의 멤버에 접근하려면 get_self<Impl>(projected)를 쓸 수 있다.
반면 make_self<Impl>은 구현 객체를 만들고 프로젝션 대신 winrt::com_ptr<Impl>을 반환한다. 이 포인터로 구현 객체의 멤버에 접근한 다음 * 연산자로 프로젝션 타입으로 바꿀 수 있다.
구현 클래스의 프로젝션에 노출되지 않는 공개 멤버에 먼저 접근할 예정이라면 com_ptr<Impl>의 -> 연산자를 쓴다. 예를 들어 프로젝션을 반환하기 전에 객체를 설정할 수 있다.
winrt::IVector<winrt::Widget>
MakeWidgets(int style, int count)
{
std::vector<winrt::Widget> v(count, nullptr);
std::generate(v.begin(), v.end(), [&] {
auto widget = winrt::make_self<implementation::Widget>(style);
widget->Enabled(true);
return *widget;
});
return winrt::multi_threaded_vector(std::move(v));
}
프로젝션만 사용할 예정이라면 구현 타입을 거치는 대신 바로 만들 수 있다.
// The long way
winrt::IVector<winrt::Widget>
MakeWidgets(int style, int count)
{
std::vector<winrt::Widget> v(count, nullptr);
std::generate(v.begin(), v.end(), [&] {
auto widget = winrt::make_self<implementation::Widget>(style);
return *widget;
});
return winrt::multi_threaded_vector(std::move(v));
}
// The short way
winrt::IVector<winrt::Widget>
MakeWidgets(int style, int count)
{
std::vector<winrt::Widget> v(count, nullptr);
std::generate(v.begin(), v.end(), [&] {
return winrt::make_self<implementation::Widget>(style);
});
return winrt::multi_threaded_vector(std::move(v));
}
이 경우 구현 타입을 거칠 필요가 없다. 내 추측으로는 긴 방식을 쓰는 사람들은 객체 생성 방법이 두 가지라는 점을 몰라 한 가지 방법만 익힌 뒤 더 짧은 방법이 있어도 계속 사용하는 것 같다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요