How to iterate a gcroot

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
 
J

Jeffrey Tan[MSFT]

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.
 
J

Jeffrey Tan[MSFT]

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.
 
J

Jeffrey Tan[MSFT]

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.
 
B

Bob Altman

"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
 
J

Jeffrey Tan[MSFT]

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.
 
B

Ben Voigt [C++ MVP]

// 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 ) { ... }
 

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