How to iterate a gcroot

  • Thread starter Thread starter Bob Altman
  • Start date Start date
B

Bob Altman

Hi all,

In C++/CLI (VS 2005) I have a C++ module compiled with /clr that contains a
module-level gcroot variable:

static gcroot<MyList^> m_myList = gcnew MyList;

In the above statement, MyList is a managed class that inherits from
Generic::List. I want to iterate through m_myList like this:

for each (MyItem^ myItem in m_myList) {
[do something with myItem]
}

but I get error c3285: for each statement cannot operate on variables of type
'gcroot<T>'

So, how do I iterate through a List that's stored in a gcroot?

TIA - Bob
 
Hi Bob,

I will perform some research on this issue and provide a reply to you ASAP.
Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
=========================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Bob,

Sorry for letting you wait.

C++/CLI "for each" statement iterates over objects that implement the
IEnumerable interface, while gcroot does not implement this interface.
Luckily, gcroot provides an operator T conversion, so you can just
static_cast in your example to the MyItem^ type. I have written a sample
using System::String^ type to demonstrate it.

// The following generates the same error as your program
#include <vcclr.h>
using namespace System;

class CppClass {
public:
gcroot<String^> str; // can use str as if it were String^
CppClass() {}
};

int main(array<System::String ^> ^args)
{
CppClass c;
c.str = gcnew String("hello");

for each ( Char c in c.str )
Console::Write(c);
return 0;
}
Error 1 error C3285: for each statement cannot operate on variables of type
'gcroot<T>'


// The following code compiles well.
#include <vcclr.h>
using namespace System;

class CppClass {
public:
gcroot<String^> str; // can use str as if it were String^
CppClass() {}
};

int main(array<System::String ^> ^args)
{
CppClass c;
c.str = gcnew String("hello");

for each ( Char c in static_cast<String^>(c.str) )
Console::Write(c);
return 0;
}

Hope it helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
=========================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Sorry, a little typo, you should static_cast in your example to the MyList^
type. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
=========================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
"Jeffrey Tan[MSFT]" said:
Hi Bob,

Sorry for letting you wait.

C++/CLI "for each" statement iterates over objects that implement the
IEnumerable interface, while gcroot does not implement this interface.
Luckily, gcroot provides an operator T conversion, so you can just
static_cast in your example to the MyItem^ type.

Thanks (as always) Jeffrey!

This also answers another question that I had. The gcroot wrapper is great
as long as you are assiging values to it or accessing members contained by
it, but I have run into other scenarios where I need to get my hands on the
actual underlying managed reference.

I submitted this as a documentation bug to Microsoft Connect:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=353206
 
Hi Bob ,

Glad to see my reply can help you. If you need further help, please feel
free to post, thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
=========================================
Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
// The following code compiles well.
#include <vcclr.h>
using namespace System;

class CppClass {
public:
gcroot<String^> str; // can use str as if it were String^
CppClass() {}
};

int main(array<System::String ^> ^args)
{
CppClass c;
c.str = gcnew String("hello");

for each ( Char c in static_cast<String^>(c.str) )
Console::Write(c);

I would suggest introducing a new variable instead of adding a cast, the
cast can hide type incompatibilities.

i.e.

String^ const s = c.str;
for each ( Char c in s ) { ... }
 
Back
Top