locked
Differences between C++/CLI and WinRT C++

    Question

  • Hi,

    I would like to know the complete details, if possible, of the differences between C++/CLI and WinRT C++. I am also curious about why WinRT doesn't support C++/CLI.

    Your answer is highly apprediated.

     

    Sincerely,

    Nyi Nyi

     


    Code |> Live |> Learn
    Tuesday, September 20, 2011 3:14 AM

Answers

  • Nishant, you're very close on your unofficial theory :). The main reason why we don't support C++/cli right now is because each language needs to do a bit of work in order to support the .NET Framework under metro (use System.Core.dll instead of mscorlib.dll, some codegen differences for events etc.). C# and VB went through those changes - but as you pointed out we have our hands full with C++/CX right now.

    In terms of the differences that are not just bugs (like [flags] as was pointed out above):

    Basic types:
    /clr: From mscorlib.dll (System::* types)
    /ZW:  From vccorlib.dll (Platform::* types)

    Lifetime management:
    /clr: Garbage collected
    /ZW:  Refcounted

    Cycles Broken:
    /clr: By garbage collector
    /ZW:  Broken by user (weak references or explicit delete)

    Code generation:
    /clr: MSIL + native code. Can create a cross-platform binary if MSIL-only.
    /ZW:  Native code only. Binaries target a specific platform.

    Object Creation:
    /clr: gcnew
    /ZW:  ref new

    interior_ptr:
    /clr: Supported
    /ZW:  Not supported

    pin_ptr:
    /clr: Supported
    /ZW:  Not supported

    V% (% when it refers to a byref (kind'a like an "interior_ref") ):
    /clr: Supported
    /ZW:  Not supported

    R% (% when it refers to an implicitly dereferenced ref type):
    /clr: Supported
    /ZW:  Supported

    Ref to ^:
    /clr: R^%
    /ZW:  R^&

    Boxing:
    /clr: syntax V^
    /ZW:  IReference<V>^

    Dereferenced box type:
    /clr: V%
    /ZW:  const V

    Generics:
    /clr: Generics classes, interfaces & delegates allowed.
    /ZW:  Generic interfaces & delegates only.

    Static constructors:
    /clr: Supported
    /ZW:  Not supported

    Address of member of ref class:
    /clr: Returns an interior_ptr
    /ZW:  Returns a type*

    friends:
    /clr: Not supported
    /ZW:  Supported

    C++ class embedded in ref class:
    /clr: Not supported
    /ZW:  Supported

    ref class embedded in C++ class:
    /clr: Not supported
    /ZW:  Supported (R-on-stack)

    ^ embedded in C++ class:
    /clr: Not supported (Needs GCHandle)
    /ZW:  Supported

    ^ embedded in value class with value class on native heap:
    /clr: Not supported
    /ZW:  Supported (for String^)

    Global ^:
    /clr: Not supported
    /ZW:  Supported

    Global R-on-stack:
    /clr: Not supported
    /ZW:  Supported

    Finalizer:
    /clr: Supported
    /ZW:  Not supported

    Destructor:
    /ZW:  Runs on IDisposable::Dispose (delete / stack unwind) only
    /clr: Runs on IDisposable::Dispose (delete / stack unwind) -or- last release (never both)

    T::typeid:
    /clr: Supported
    /ZW:  Not supported

     

    PS: R-on-stack (ref class on stack) syntax is supported on C++/cli and C++/CX, but you'll notice that unfortunately the /CX implementation in the developer preview release has a code generation bug that will make it impractical to test this right now. (R^ and R% should be fine though). The most important reason for R-on-stack is exception-safe destruction (Like 'using' gives you in C#) - other than that it is purely compiler syntactic sugar.

     

    Hope this helps!

    -----------------------
    Deon Brewis
    Principal Architect
    Visual C++

    Wednesday, September 21, 2011 5:38 PM
  • I found out these: gcnew -> ref new, no initonly support, [Flags] for enums wont work (but this is listed in the reference page, so I guess it is supposed to work). And, I think you can create WinRT ref class object on stack which is not allowed in C++/CLI.

    Other than the gcnew vs ref new difference that WalkingCat mentioned, C++/CX has no concept of interior_ptr/pin_ptr (since it's native code).

    BTW one correction to WalkingCat's post. WinRT objects can use stack semantics but that's compiler magic for you, since the actual code generated will create them on the heap. This was the same with C++/CLI too where it supported stack semantics but the code generated created objects on the CLR-heap.

    This is my unofficial theory as to why they did not support C++/CLI for RT : C# and VB have full parity with .NET (specially the features added in .NET 4.0/4.5) whereas C++/CLI has not been improved since .NET 3.0. So it would have been a bit of a task to get C++/CLI up to speed and then support WinRT. Specially since they had their hands full getting the C++/CX stuff working fine. I also believe the C++/CLI intellisense that we get is a side-effect of the fact that they had to add intellisense for C++/CX anyway.


    http://blog.voidnish.com
    • Marked as answer by Nyi Nyi Thann Thursday, September 22, 2011 1:52 AM
    Tuesday, September 20, 2011 11:20 AM

All replies

  • I found out these: gcnew -> ref new, no initonly support, [Flags] for enums wont work (but this is listed in the reference page, so I guess it is supposed to work). And, I think you can create WinRT ref class object on stack which is not allowed in C++/CLI.
    Tuesday, September 20, 2011 5:40 AM
  • I found out these: gcnew -> ref new, no initonly support, [Flags] for enums wont work (but this is listed in the reference page, so I guess it is supposed to work). And, I think you can create WinRT ref class object on stack which is not allowed in C++/CLI.

    Other than the gcnew vs ref new difference that WalkingCat mentioned, C++/CX has no concept of interior_ptr/pin_ptr (since it's native code).

    BTW one correction to WalkingCat's post. WinRT objects can use stack semantics but that's compiler magic for you, since the actual code generated will create them on the heap. This was the same with C++/CLI too where it supported stack semantics but the code generated created objects on the CLR-heap.

    This is my unofficial theory as to why they did not support C++/CLI for RT : C# and VB have full parity with .NET (specially the features added in .NET 4.0/4.5) whereas C++/CLI has not been improved since .NET 3.0. So it would have been a bit of a task to get C++/CLI up to speed and then support WinRT. Specially since they had their hands full getting the C++/CX stuff working fine. I also believe the C++/CLI intellisense that we get is a side-effect of the fact that they had to add intellisense for C++/CX anyway.


    http://blog.voidnish.com
    • Marked as answer by Nyi Nyi Thann Thursday, September 22, 2011 1:52 AM
    Tuesday, September 20, 2011 11:20 AM
  • Hi WalkingCAt and Nishant,

    Thanks for the answers.

    I am still awaiting more answers.

     

    Sincerely,

    Nyi Nyi


    Code |> Live |> Learn
    Wednesday, September 21, 2011 5:49 AM
  • Nishant, you're very close on your unofficial theory :). The main reason why we don't support C++/cli right now is because each language needs to do a bit of work in order to support the .NET Framework under metro (use System.Core.dll instead of mscorlib.dll, some codegen differences for events etc.). C# and VB went through those changes - but as you pointed out we have our hands full with C++/CX right now.

    In terms of the differences that are not just bugs (like [flags] as was pointed out above):

    Basic types:
    /clr: From mscorlib.dll (System::* types)
    /ZW:  From vccorlib.dll (Platform::* types)

    Lifetime management:
    /clr: Garbage collected
    /ZW:  Refcounted

    Cycles Broken:
    /clr: By garbage collector
    /ZW:  Broken by user (weak references or explicit delete)

    Code generation:
    /clr: MSIL + native code. Can create a cross-platform binary if MSIL-only.
    /ZW:  Native code only. Binaries target a specific platform.

    Object Creation:
    /clr: gcnew
    /ZW:  ref new

    interior_ptr:
    /clr: Supported
    /ZW:  Not supported

    pin_ptr:
    /clr: Supported
    /ZW:  Not supported

    V% (% when it refers to a byref (kind'a like an "interior_ref") ):
    /clr: Supported
    /ZW:  Not supported

    R% (% when it refers to an implicitly dereferenced ref type):
    /clr: Supported
    /ZW:  Supported

    Ref to ^:
    /clr: R^%
    /ZW:  R^&

    Boxing:
    /clr: syntax V^
    /ZW:  IReference<V>^

    Dereferenced box type:
    /clr: V%
    /ZW:  const V

    Generics:
    /clr: Generics classes, interfaces & delegates allowed.
    /ZW:  Generic interfaces & delegates only.

    Static constructors:
    /clr: Supported
    /ZW:  Not supported

    Address of member of ref class:
    /clr: Returns an interior_ptr
    /ZW:  Returns a type*

    friends:
    /clr: Not supported
    /ZW:  Supported

    C++ class embedded in ref class:
    /clr: Not supported
    /ZW:  Supported

    ref class embedded in C++ class:
    /clr: Not supported
    /ZW:  Supported (R-on-stack)

    ^ embedded in C++ class:
    /clr: Not supported (Needs GCHandle)
    /ZW:  Supported

    ^ embedded in value class with value class on native heap:
    /clr: Not supported
    /ZW:  Supported (for String^)

    Global ^:
    /clr: Not supported
    /ZW:  Supported

    Global R-on-stack:
    /clr: Not supported
    /ZW:  Supported

    Finalizer:
    /clr: Supported
    /ZW:  Not supported

    Destructor:
    /ZW:  Runs on IDisposable::Dispose (delete / stack unwind) only
    /clr: Runs on IDisposable::Dispose (delete / stack unwind) -or- last release (never both)

    T::typeid:
    /clr: Supported
    /ZW:  Not supported

     

    PS: R-on-stack (ref class on stack) syntax is supported on C++/cli and C++/CX, but you'll notice that unfortunately the /CX implementation in the developer preview release has a code generation bug that will make it impractical to test this right now. (R^ and R% should be fine though). The most important reason for R-on-stack is exception-safe destruction (Like 'using' gives you in C#) - other than that it is purely compiler syntactic sugar.

     

    Hope this helps!

    -----------------------
    Deon Brewis
    Principal Architect
    Visual C++

    Wednesday, September 21, 2011 5:38 PM
  • Awesome comprehensive answer, Deon. Thank you!
    http://blog.voidnish.com
    Wednesday, September 21, 2011 6:08 PM
  • Hi Deon,

     

    Thank so much for the awesome answer.

     

    Regards,

    Nyi Nyi


    Code |> Live |> Learn
    Thursday, September 22, 2011 1:54 AM
  • Ref to ^:
    /clr: R^%
    /ZW:  R^&
    What's the reasoning behind that difference? What effect (if any) might it have on generic code intended to be shared between CLI and RT programs?
    Thanks!
    Wednesday, November 2, 2011 8:55 AM
  • Ref to ^:
    /clr: R^%
    /ZW:  R^&
    What's the reasoning behind that difference? What effect (if any) might it have on generic code intended to be shared between CLI and RT programs?
    Thanks!

    I reckon Deon can give an official answer. But in C++/CLI % clearly indicates a tracking reference to a GC type. In WinRT the references are not GC'd and will not really get moved around in memory, so & makes better sense from a syntactic perspective.
    http://blog.voidnish.com
    Wednesday, November 2, 2011 2:16 PM
  • Sorry to only reply now. Didn't see this earlier.

    The reason is as Nishant mentioned, that it isn't needed since the objects don't get moved.

    However, more importantly, this gives MUCH better interoperability with existing libraries.

    E.g. you can use 'R^' anywhere inside the STL where a 'T' is taken, and STL can happily form T, T*, T& and T&& (where T is R^) wherever it needs it.

    Sunday, April 15, 2012 4:24 PM