Closed JaiganeshKumaran closed 1 year ago
The relationship between optimizations and static factories is regrettably complex but isn't something we can easily fix without a major overhaul.
Could you provide a generated base class for the implementation type that will automatically call into the factory instead? Obviously, with this, the factory needs to be defined first, which isn't a problem for static classes (can specify the factory instead as the second template parameter of factory_implementation::YourTypeT) but won't work for classes that can be instantiated.
Here's a simple solution.
namespace winrt::Component
{
template <int = 0>
static auto GetObjectHelperStatics()
{
if constexpr (winrt::impl::has_static_lifetime_v<factory_implementation::Foo>)
{
return winrt::make_self<factory_implementation::Foo>();
}
else
{
// statics_type will be a new alias on the factory based on FooT's second template parameter.
// Will cause undefined behaviour if the methods that are supposed to be static are not.
// But that cannot be the case since the factory type does T::StaticMethod()
// And that cannot work unless the method is actually static as long as T is not the same as the factory type.
return std::add_pointer_t<factory_implementation::Foo::statics_type>{ nullptr };
}
}
void Foo::StaticMethod()
{
// Before
return implementation::Foo::StaticMethod();
// After.
return GetObjectHelperStatics()->StaticMethod();
}
}
When component optimisations are enabled, to have a static lifetime factory and define the static methods in the factory, rather than the implementation type, you need to write static forwarders in the implementation type as shown here: https://learn.microsoft.com/en-us/uwp/cpp-ref-for-winrt/static-lifetime#examples.
Consider making the generated code in g.cpp call into the factory directly if the static_lifetime marker is present instead of calling the static method on the implementation type.