From: JohnR on 28 Sep 2009 09:33 Hi there, I'm new to C++/CLI but very experierced in both C++ and .NET. Can someone show me the basic syntax for converting a List<T> to vector<T> (or more generally, any .NET generic to its C++ template equivalent). For now I'm looking for a template with a signature similar to the following (note however that "T" would also need to be converted presumably so a template arg and a generic arg may be required). Thanks in advance. std::vector<T> marshal_as(System::Collections::Generic::List<T> ^ const & list)
From: Ben Voigt [C++ MVP] on 28 Sep 2009 12:29 "JohnR" <_no_spam@_no_spam.com> wrote in message news:#1hpNBEQKHA.1268(a)TK2MSFTNGP04.phx.gbl... > Hi there, > > I'm new to C++/CLI but very experierced in both C++ and .NET. Can someone > show me the basic syntax for converting a List<T> to vector<T> (or more > generally, any .NET generic to its C++ template equivalent). For now I'm > looking for a template with a signature similar to the following (note > however that "T" would also need to be converted presumably so a template > arg and a generic arg may be required). Thanks in advance. > > std::vector<T> marshal_as(System::Collections::Generic::List<T> ^ const & > list) Returning vector by value is going to have really bad performance unless you have the move optimization. For types which have dual managed/native identity (i.e. built-in numeric types), something like: template<typename T> std::vector<T> marshal_as(System::Collections::Generic::ICollection<T>^ list) { if (list == nullptr) throw gcnew ArgumentNullException(L"list"); std::vector<T> result(list->Count); for each (T& elem in list) result.push_back(elem); return result; } More generally, something like: template<typename T> generic<typename S> std::vector<T> marshal_as(System::Collections::Generic::ICollection<S>^ list) { if (list == nullptr) throw gcnew ArgumentNullException(L"list"); std::vector<T> result(list->Count); for each (S& elem in list) result.push_back(marshal_as<T>(elem)); return result; } Not compile-tested.
From: Victor Bazarov on 28 Sep 2009 13:03 Ben Voigt [C++ MVP] wrote: > > > "JohnR" <_no_spam@_no_spam.com> wrote in message > news:#1hpNBEQKHA.1268(a)TK2MSFTNGP04.phx.gbl... >> Hi there, >> >> I'm new to C++/CLI but very experierced in both C++ and .NET. Can >> someone show me the basic syntax for converting a List<T> to vector<T> >> (or more generally, any .NET generic to its C++ template equivalent). >> For now I'm looking for a template with a signature similar to the >> following (note however that "T" would also need to be converted >> presumably so a template arg and a generic arg may be required). >> Thanks in advance. >> >> std::vector<T> marshal_as(System::Collections::Generic::List<T> ^ >> const & list) > > Returning vector by value is going to have really bad performance unless > you have the move optimization. > > For types which have dual managed/native identity (i.e. built-in numeric > types), something like: > > template<typename T> > std::vector<T> marshal_as(System::Collections::Generic::ICollection<T>^ > list) > { > if (list == nullptr) throw gcnew ArgumentNullException(L"list"); > std::vector<T> result(list->Count); > for each (T& elem in list) > result.push_back(elem); That's A BAD IDEA(tm). You're going to end up with the vector that has its first list->Count elements default-initialized and the actual meaningful elements that follow (and total of list->Count*2 elements). Perhaps you meant std::vector<T> result; result.reserve(list->Count); for each (... Or maybe you meant std::vector<T> result(list->Count); for (int i = 0; ... result[i] = list->??? ; // or use iterators > return result; > } > > More generally, something like: > > template<typename T> > generic<typename S> > std::vector<T> marshal_as(System::Collections::Generic::ICollection<S>^ > list) > { > if (list == nullptr) throw gcnew ArgumentNullException(L"list"); > std::vector<T> result(list->Count); > for each (S& elem in list) > result.push_back(marshal_as<T>(elem)); Same notes as above. > return result; > } > > Not compile-tested. V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask
From: JohnR on 28 Sep 2009 13:26 Thanks for the feedback. I've literally just started playing with C++/CLI in the past 24 hours. It's not entirely clear to me yet what the rules are for mixing managed and unmanaged types, let alone templates and generics. See comments below. > Returning vector by value is going to have really bad performance unless > you have the move optimization. > For types which have dual managed/native identity (i.e. built-in numeric > types), something like: > > template<typename T> > std::vector<T> marshal_as(System::Collections::Generic::ICollection<T>^ > list) > { > if (list == nullptr) throw gcnew ArgumentNullException(L"list"); > std::vector<T> result(list->Count); > for each (T& elem in list) > result.push_back(elem); > return result; > } This works (thanks) but can you freely mix managed and unmanaged types. If "T" is a "long" for instance, it's 64 bits managed and 32 bits unmanaged (on a 32 bit system in the latter case). So what are the rules for mixing them like this (or rather, what does "T" mean in the case of "ICollection<long>" for instance). Note that even for types that are the same ("int" for instance, at least on a 32-bit platform), can you freely mix the managed and unmanaged version (isn't it like mixing apples and oranges, even they map to the same thing). > More generally, something like: > > template<typename T> > generic<typename S> > std::vector<T> marshal_as(System::Collections::Generic::ICollection<S>^ > list) > { > if (list == nullptr) throw gcnew ArgumentNullException(L"list"); > std::vector<T> result(list->Count); > for each (S& elem in list) > result.push_back(marshal_as<T>(elem)); > return result; > } This is what I was really after. I'm getting an internal compiler error however, first I've seen since VC6 (used to get them all the time). I'll have to play with it to see if it's possible to correct but at least I can see the basic syntax. Thanks for your help.
From: Ben Voigt [C++ MVP] on 28 Sep 2009 15:02
> That's A BAD IDEA(tm). You're going to end up with the vector that has > its first list->Count elements default-initialized and the actual > meaningful elements that follow (and total of list->Count*2 elements). > Perhaps you meant > > std::vector<T> result; > result.reserve(list->Count); > for each (... Yes, reserve is what I intended. Sorry about that. |