vector-like wrapper for IList

  • Thread starter Christian Schmidt
  • Start date
C

Christian Schmidt

Hi all,
I'm trying to implement a std::vector-like wrapper for IList.
The hard part seems to be operator[], because it returns an unmanaged
reference. Probably I have to use pin_ptr to achieve this, but I don't
know how.
Can anybody help?

Thanks,
Christian


template <typename T>
class IListWrapper {
public:
IListWrapper(IList<T>^ _list) : list(_list) { }
T& operator[](unsigned i) { return list->default; }
const T& operator[](unsigned i) { return list->default; }
unsigned size() const { return list->Count; }
void push_back(const ItemType& item) { list->Add(item); }
protected:
gcroot<IList<ItemType>^> list;
};

void main() {
IListWrapper<double> list(gcnew List<double>(10));
list[3] = 7.5;
}
 
C

Carl Daniel [VC++ MVP]

Christian said:
Hi all,
I'm trying to implement a std::vector-like wrapper for IList.
The hard part seems to be operator[], because it returns an unmanaged
reference. Probably I have to use pin_ptr to achieve this, but I don't
know how.
Can anybody help?

You can't do it like that. pin_ptr by design must be a local
(stack-allocated) variable, which means that any pin_ptr your operator[]
declares will go out of scope, unpinning the value before the operator
returns.

Unfortunately, I think you're probably going to have to return some kind of
proxy object (a la vector<bool>) to simulate the std::vector interface on an
IList<T>. The proxy object would have an operator T() and an
operator=(const T&) so it can stand-in for a 'T' in many contexts - but not
all. The proxy object would hold onto a T^ and perform the native <-->
managed conversions in the two conversion functions.

-cd
 
C

Christian Schmidt

Hi Carl,
thanks for your answer.
I'm trying to implement a std::vector-like wrapper for IList.
The hard part seems to be operator[], because it returns an unmanaged
reference. Probably I have to use pin_ptr to achieve this, but I don't
know how.
Can anybody help?

You can't do it like that. pin_ptr by design must be a local
(stack-allocated) variable, which means that any pin_ptr your operator[]
declares will go out of scope, unpinning the value before the operator
returns.

So I would need to pin the list in the constructor. Is this a problem?
How would I proceed?
Unfortunately, I think you're probably going to have to return some kind of
proxy object (a la vector<bool>) to simulate the std::vector interface on an
IList<T>. The proxy object would have an operator T() and an
operator=(const T&) so it can stand-in for a 'T' in many contexts - but not
all. The proxy object would hold onto a T^ and perform the native <-->
managed conversions in the two conversion functions.

Will this work for value types in the IList, too? Or do I have to use
the setter of the IList?


Is this a correct implementation of the Proxy?

template <typename T>
class ReferenceWrapper {
public:
ReferenceWrapper(T^ _me) : me (_me) { }
ReferenceWrapper<T> operator=(const T& other) {
me = other;
return *this;
}
operator T() { return *(T^) me; }
protected:
gcroot<T^> me;
};
 
C

Carl Daniel [VC++ MVP]

Christian said:
Hi Carl,
thanks for your answer.
I'm trying to implement a std::vector-like wrapper for IList.
The hard part seems to be operator[], because it returns an
unmanaged reference. Probably I have to use pin_ptr to achieve
this, but I don't know how.
Can anybody help?

You can't do it like that. pin_ptr by design must be a local
(stack-allocated) variable, which means that any pin_ptr your
operator[] declares will go out of scope, unpinning the value before
the operator returns.

So I would need to pin the list in the constructor. Is this a problem?
How would I proceed?

No, you can't have a pin_ptr as a member variable. You have to pin it,
reference it, and un-pin it in each invocation of operator T() or operator=
(const T&).
Will this work for value types in the IList, too? Or do I have to use
the setter of the IList?


Is this a correct implementation of the Proxy?

Something like that, yes.

-cd
 
B

Ben Voigt [C++ MVP]

Christian Schmidt said:
Hi Carl,
thanks for your answer.
I'm trying to implement a std::vector-like wrapper for IList.
The hard part seems to be operator[], because it returns an unmanaged
reference. Probably I have to use pin_ptr to achieve this, but I don't
know how.
Can anybody help?

You can't do it like that. pin_ptr by design must be a local
(stack-allocated) variable, which means that any pin_ptr your operator[]
declares will go out of scope, unpinning the value before the operator
returns.

So I would need to pin the list in the constructor. Is this a problem? How
would I proceed?
Unfortunately, I think you're probably going to have to return some kind
of proxy object (a la vector<bool>) to simulate the std::vector interface
on an IList<T>. The proxy object would have an operator T() and an
operator=(const T&) so it can stand-in for a 'T' in many contexts - but
not all. The proxy object would hold onto a T^ and perform the native
<--> managed conversions in the two conversion functions.

Will this work for value types in the IList, too? Or do I have to use the
setter of the IList?

To implement operator[] assignment, yes, you'll need to use the IList
setter.

Either your caller needs to be managed type aware, in which case you don't
need pinning pointers at all, or you have a managed collection of primitive
types. Can you fill in some of the blanks here?

Maybe all you are looking for is the T^% tracking reference syntax.
Is this a correct implementation of the Proxy?

template <typename T>
class ReferenceWrapper {
public:
ReferenceWrapper(T^ _me) : me (_me) { }
ReferenceWrapper<T> operator=(const T& other) {

It's customary to return a reference.
me = other;

Need to dereference me here, ala (*me = other), or else reassign me to a new
valid handle, which other isn't.
return *this;
}
operator T() { return *(T^) me; }

The compiler should choke on that if T is a class type. If it isn't, why
are you boxing it (T^ to a value type incurs boxing).
protected:
gcroot<T^> me;
};


Look up interior_ptr<T>.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top