microsoft / cppwinrt

C++/WinRT
MIT License
1.64k stars 238 forks source link

C2259 when instantiate class with parameterized constructor in debug mode #1311

Closed ACGNnsj closed 1 year ago

ACGNnsj commented 1 year ago

Version

2.0.230225.1

Summary

It's a long story. At first, I would like to imitate the templates code and use winrt::make to get class instances. However, the codes didn't compile, and thus I tried to use the constructor and succeeded. Then I added a single-parameter constructor and it also worked well. Afterwards, I failed to assign the instance to a member variable with error C2280, and I tried to add a copy constructor. Then, I encountered MIDL4061 'More than one factory method with same number of arguments in the projected constructors'. Follow the instruction literally, I add a redundant parameter to the original single-parameter constructor but failed again. At last, I changed everything back. The codes could still be compiled then in release mode, while I found the compilation failed in debug mode the next day. There came error C2259 and the IDE showed something like 'XXX::use_make_function_to_create_this_object(XXX) is pure virtual'. I could do nothing but return to winrt::make and it worked. I don't resist to use winrt::make, but just would like to work out what was happening.

Reproducible example

The old one. And the current project. Problems center around OverlayPanel.

Expected behavior

Able to get instances through either winrt::make or constructor.

Actual behavior

Only winrt::make works.

Additional comments

No response

sylveon commented 1 year ago

It sounds to me like you where trying to stack allocate an instance of implementation::OverlayPanel - don't do that. Either use com_ptr<implementation::OverlayPanel> (which winrt::make_self gives you), or use the OverlayPanel projection type (which can be constructed directly or gotten through winrt::make)

ACGNnsj commented 1 year ago

Thanks for your reply. Does that mean the way of instantiation here is not suggested? The most confusing thing is that this way worked then, but doesn't work now. Since OverlayPanel self hasn't change, could the generated codes of it be changed due to some other new codes?

sylveon commented 1 year ago

It breaks in your case due to sharing a namespace for both classes. You can avoid this problem by specifying OCR::OverlayPanel

ACGNnsj commented 1 year ago

Thanks, it worked. Here is another confusing thing to me that since a stack-allocated object should be destroyed by cl automatically, but the corresponding UI element still behaves well. Could I consider that this object is disposable or consumable?

sylveon commented 1 year ago

When you use OCR::OverlayPanel, you're not actually stack allocating it. You are heap allocating it (WinRT objects are reference counted), and the element stays alive because the Window object keeps a reference to it. It's illegal to stack allocate WinRT objects, which is what the use_make_function_to_create_this_object is trying to allude to.

ACGNnsj commented 1 year ago

Thanks a lot!