Update:

Based on Ryan Shepherd's reply, I changed my code to:

class DerivedClass : winrt::implements<DerivedClass, BaseClass> {
public:
DerivedClass(winrt::FrameworkElement& control) : 
5===>implements_type(control) {}

static winrt::com_ptr<DerivedClass> from(winrt::FrameworkElement control) { 
    control ? control.Tag().try_as<SvgCanvasController>() : nullptr;
}
}

Now I get an error:

no instance of constructor "winrt::implements<D, I, ...>::implements [with D=DerivedClass, I=BaseClass]" matches the argument list argument types are: (winrt::Windows::UI::Xaml::FrameworkElement).

I do have BaseClass Constructor defined which takes in &FrameworkElement as an argument. So I am not sure what I am getting this error.

Original:

I had this in C++/CX:

ref class DerivedClass sealed : public BaseClass {
public:
explicit DerivedClass(Windows::UI::Xaml::FrameworkElement^ &control)
    : BaseClass(control) {}

static DerivedClass from(Windows::UI::Xaml::FrameworkElement^ control) {
    return control ? dynamic_cast<DerivedClass>(control->Tag) : nullptr;
}   
}

when I try to convert this to c++/winrt

class DerivedClass : winrt::implements<DerivedClass, BaseClass> {
public:
1===>DerivedClass(winrt::FrameworkElement& control) : BaseClass(control) 
2===>{
}

static DerivedClass from(winrt::FrameworkElement control) { 
    if (control)
 3===>       return control.Tag().try_as<SvgCanvasController>();
    else
 4===>       return nullptr;
}

There are a few issues here I want to discuss and understand. As it is written above, I get the following errors:

1

BaseClass is not a non-static data member or base class of class DerivedClass

2

default constructor of winrt::implements<DerivedClass, BaseClass> cannot be referenced -- it is a deleted function

3

No suitable user defined conversion from winrt::impl::com_ref<DerivedClass> to DerivedClass

4

no suitable constructor exists to convert from std::nullptr_t to DerivedClass

Would love some thoughts on these errors.

I understand I create a DerivedClass object as

auto obj = winrt::make<DerivedClass>();

Questions:

  1. How do I write the constructor properly?
  2. How can i pass the argument to the base class constructor like I do in C++/CX?
  3. How can I deal with the errors in the from() function definition.
1

There are 1 best solutions below

2
On

Regarding the first error, DerivedClass doesn't inherit from BaseClass, it inherits from winrt::implements<DerivedClass, BaseClass>, which then derives from BaseClass. A grandchild class can't directly initialize its grandparent - it most go through its immediate base type. Fortunately, C++/WinRT provides a helper type in winrt::implements so you don't have to repeat all those template params. So, your constructor should look like this:

#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.UI.Xaml.h>

using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Xaml;

struct BaseType : implements<BaseType, IInspectable>
{
    explicit BaseType(FrameworkElement const&)
    {}
};

struct DerivedType : implements<DerivedType, BaseType>
{
    explicit DerivedType(FrameworkElement const& arg)
        : implements_type(arg)
    {}
};

int main()
{
    make<DerivedType>(FrameworkElement{ nullptr });
}

This code compiles successfully for me.

The other three errors are due to the fact that you are attempting to return an implementation type directly on the stack. These objects are reference counted, and must be allocated on the heap, which you appear to understand due to calling out winrt::make. But the rest of the equation is that instead of returning a DerivedClass, you need to return winrt::com_ptr<DerivedClass>, resulting in something like this:

static winrt::com_ptr<Derived> from(winrt::FrameworkElement const& arg)
{
  return arg ? arg.Tag().try_as<DerivedClass>() : nullptr;
}