C++/CLI language design questions

I'm doing another C++/CLI project that involves porting some of my native C++ classes so that I can mix both native and managed code.  And I'm hitting the same issues often enough to wonder about a few things about the C++/CLI language design.

One of the major changes from the old C++/CLI syntax to the new one is that you cannot have an unmanaged class member of a ref class.  

e.g.
class U
{
...
};

ref class M
{
   U u; // causes C4368: mixed types are not supported
};
   
This is because memory locations for instances of M can change, and there is a risk of using the address of u somewhere in unmanaged code after it has changed.

The workaround I've been using is to use U* u, and then use new/delete in the constructor/destructor, respectively.   So far this has been a pretty mechanical process, but it also introduces additonal risk that I could leave a memory leak behind or delete things out of order in the destructor (in the native C++ version, some of my nested objects take references of one another).

I wonder if the language could have supported the original code (POD I think people called it) by treating U u as a hidden indirection (transparent to me).  There should be enough information during construction to do the implicit new: if constructor arguments were needed for U, then any C++ syntax would give an error.  The implicit delete might be a bit hairier.

Also, another change between the two Managed C++ versions is the introducution of ^ versus the ambiguous *, which was used to reference either an unmanaged type or a managed type.  This seems to be a good thing, but I wish that I could be using the '.' notation rather that ->.  It is cleaner and more intuitive since the managed ^ is more like an unmanaged & than an unmanged *.  In many (or all ) cases where I accidentally use '.' instead, the compiler emits a warning and tells me that it's assuming ->.  Why not restrict the -> operator to just pointers (*) and use '.' for handles

Brian



Answer this question

C++/CLI language design questions

  • Jeremy_AK

    Yeah, Brandon's article was useful, and I'm glad I read it before I got heavy into C++/CLI coding.  Not having unmanaged POD's in managed classes seems like a big hit on the language, and I was sharing my the issues I have with it and suggesting a compiler feature that might bring it back.

    Thanks for the stack-based syntax.  I forgot about that...

    Brian

  • selwonk

    Brandon Bray from the Visual C++ team has a detailed blog post motivating the design for mixed types:

    http://blogs.msdn.com/branbray/archive/2005/07/20/441099.aspx

    Also, C++/CLI supports stack-based syntax for managed types, so you can use the '.' notation:

    http://msdn2.microsoft.com/en-us/library/ms177191.aspx

    Thanks,
    Mitch



  • byebyestar

    In some cases, the translation from native C++ is more painful.  I need to have a vector<string> member, but after changing to a pointer and using new in the constructor, my code ends up looking like this.

    (with vector<string>* columns)

    for( size_t i = firstYCol; i < columns->size(); i++ )
    {   
       (*columns)[ i ] =
    (*columns)[ i ] + "%";
    }

    The point being that I can't use some overloaded operators without first dereferencing as a parenthesized expression. 

    Also, during this conversion process, I'm not bothering to assert that these member pointers are non-null, because are too many of them (it is below my "should I assert this" threshold).  I fall back on the assumption that constructors did new (which might be wrong in some cases), and that my destructor will not call dependent functions after delete.




  • Ryszard Kwiecinski - MSFT

     Brian_Kramer wrote:
    Also, another change between the two Managed C++ versions is the introducution of ^ versus the ambiguous *, which was used to reference either an unmanaged type or a managed type.  This seems to be a good thing, but I wish that I could be using the '.' notation rather that ->.  It is cleaner and more intuitive since the managed ^ is more like an unmanaged & than an unmanged *.  In many (or all ) cases where I accidentally use '.' instead, the compiler emits a warning and tells me that it's assuming ->.  Why not restrict the -> operator to just pointers (*) and use '.' for handles


    I'm going to answer my own question on this one.  After using the language for a while, I realize that -> is a better choice after all for at least two reasons.
    1. If this is a handle, then this->method() matches standard C++ syntax.
    2. -> is overloadable, which allows things like gcroot template to do its magic.

    But I'm still curious about the possibility of using hidden indirection to enable unmanaged members inside managed members.



  • C++/CLI language design questions