views:

187

answers:

3

We have a C++ library which uses a struct containing an STL vector of structs, like so:

struct Params
{
    // values...
}

struct Settings
{
    std::vector<Params> m_params;

    // values...
}

I'm writing a CLI wrapper for the library, and I want equivalents for the above struct types. I had been thinking about using a List as the equivalent of a vector, like so:

public value struct Params
{
    // values...
}

public value struct Settings
{
    List<Params>^ Params;

    // values...
}

But since List<T> is a reference type, the list gets passed around by reference rather than value. Is there a way of creating a CLI class containing a list (or similar) which is passed by value, along with the rest of the members?

+1  A: 

I don't think you can pass your Settings class around by value because "value types cannot contain user-defined special member functions" (from C3417) such as the copy constructor.

You can achieve a similar effect using:

public value struct Settings : public ICloneable
{
    List<Params>^ m_params;

    virtual Object^ Clone()
    {
        Settings^ rv = gcnew Settings();
        rv->m_params = gcnew List<Params>();
        rv->m_params->AddRange(m_params->ToArray());
        return rv;
    }
}

In your C# code you would then have:

Settings s1, s2;
// ... some code modifying s1
s2 = (Settings)s1.Clone();

which is nearly as clean as the Settings settings1 = settings2; style syntax you get with pass by value.

mcdave
A: 

How about List<Params>^% Params; alternatively List<Params%>^% Params;?

Fredrik Ullner
+1  A: 

I agree with mcdave's answer, which boils down to that what you are asking is not supported.

I am speculating that your main point is not to get actual pass-by-value, but more to get pass-by-value behavior. Think of System.String. That is not really a value type, but you can pass the references around safely because strings can't be modified, you can only make new ones.

To get the same for a list, you can make Params a property of type IList<Param>. When assigning it, copy the contents into a new List<Param> and store the IList pointer you get when calling AsReadOnly(). From now on, the IList points to an object that can't be modified. If the struct is passed by value, the pointer will be copied but that's OK because it points to something immutable. If your object gets passed around a lot, it will also be faster, because there's no need for a deepcopy everytime.

jdv
You're quite right - string-equivalent behaviour would be good enough.
Simon