Trouble porting simple class from MEC++ to C++/CLI

B

Bern McCarty

I have a simple ref class in its own namespace that needs to coexist with
a legacy typedef alias for "unsigned int" in the global namespace that has
the identifier as itself. Everything compiles fine with the old MEC++ syntax,
but I cannot figure out how to write the code so that it will compile in
C++/CLI. Can someone tell me how? Here is the code in both syntaxes:

// This MEC++ code compiles just fine with VC8 using cl -c -clr:blush:ldsyntax
StaticClassOldSyntax.cpp

typedef unsigned int LevelID;

namespace Test
{
public __value class LevelID
{
public private: System::UInt32 m_id;

public private: LevelID(System::UInt32 const __gc&
nlid);

public: static ::LevelID op_Explicit (LevelID const lid);
public: static LevelID op_Explicit :):LevelID const nlid);

public: static bool op_Equality(LevelID const l1, LevelID
const l2);
public: static bool op_Inequality(LevelID const l1, LevelID
const l2);

public: virtual bool Equals(System::Object* obj);
public: virtual int GetHashCode();
public: virtual System::String* ToString();
};

public __abstract __sealed __gc class LevelIDs
{
public: static const ::Test::LevelID ApplicationInfo = 20u;
};




/* This fails to compile with VC8 using cl -c -clr StaticClass.cpp. It results
in:

Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.42
for Microsoft (R) .NET Framework version 2.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.

StaticClass.cpp
StaticClass.cpp(27) : error C2061: syntax error : identifier 'LevelID'
This diagnostic occurred in the compiler generated function 'void
Test::LevelIDs::LevelIDs(void)'

*/
typedef unsigned int LevelID;

namespace Test
{
public value class LevelID
{
internal: System::UInt32 m_id;

internal: LevelID(System::UInt32 const% nlid);

public: static explicit operator ::LevelID(LevelID const lid);
public: static explicit operator LevelID:):LevelID const nlid);

public: static bool operator ==(LevelID const l1, LevelID const l2);
public: static bool operator !=(LevelID const l1, LevelID const l2);

public: virtual bool Equals(System::Object ^ obj) override;
public: virtual int GetHashCode() override;
public: virtual System::String^ ToString() override;
};


public ref class LevelIDs abstract sealed
{
public: initonly static ::Test::LevelID ApplicationInfo = static_cast<::Test::LevelID>(20u);
};

}
 
C

Carl Daniel [VC++ MVP]

Bern said:
I have a simple ref class in its own namespace that needs to coexist
with a legacy typedef alias for "unsigned int" in the global namespace
that has the identifier as itself. Everything compiles fine with the old
MEC++ syntax, but I cannot figure out how to write the code so that it
will compile
in C++/CLI. Can someone tell me how? Here is the code in both syntaxes:

// This MEC++ code compiles just fine with VC8 using cl -c
-clr:blush:ldsyntax StaticClassOldSyntax.cpp

typedef unsigned int LevelID;

namespace Test
{
public __value class LevelID
{
public private: System::UInt32 m_id;

public private: LevelID(System::UInt32 const
__gc& nlid);

public: static ::LevelID op_Explicit (LevelID const
lid); public: static LevelID op_Explicit :):LevelID
const nlid);
public: static bool op_Equality(LevelID const l1,
LevelID const l2);
public: static bool op_Inequality(LevelID const
l1, LevelID const l2);

public: virtual bool Equals(System::Object* obj);
public: virtual int GetHashCode();
public: virtual System::String* ToString();
};

public __abstract __sealed __gc class LevelIDs
{
public: static const ::Test::LevelID ApplicationInfo = 20u;
};




/* This fails to compile with VC8 using cl -c -clr StaticClass.cpp. It
results in:

Microsoft (R) C/C++ Optimizing Compiler Version 14.00.50727.42
for Microsoft (R) .NET Framework version 2.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.

StaticClass.cpp
StaticClass.cpp(27) : error C2061: syntax error : identifier
'LevelID' This diagnostic occurred in the compiler
generated function 'void Test::LevelIDs::LevelIDs(void)'

Have you tried explicitly defining the default constructor? Since that's
where the compiler is getting tripped up, it seems like a good place to
start.

-cd
 
B

Bern McCarty

But my class is a static class on purpose (i.e. it is both abstract and sealed).
In such class you are not allowed to have any instance methods, including
constructors. If you try to add one you'd get:

'Test::LevelIDs': a sealed abstract class cannot have any instance members

So it is very bizarre that the compiler error message indicates that it is
getting tripped up in a constructor that I do not have and that I am not
allowed to have. I wonder if the error message is simply wrong and it is
really referring to .cctor (a class constructor) ?

At any rate, this is an awfully simple little compiland and I have no idea
how to make it fly in C++/CLI. I'm surprised to have my syntax porting effort
hung up on such simple things.

-Bern
 
C

Carl Daniel [VC++ MVP]

Bern said:
But my class is a static class on purpose (i.e. it is both abstract
and sealed). In such class you are not allowed to have any instance
methods, including constructors. If you try to add one you'd get:

'Test::LevelIDs': a sealed abstract class cannot have any instance
members


Sorry, I misred the error - I thought it was the constructor for LevelID
that was the source of the error, not LevelIDs.
So it is very bizarre that the compiler error message indicates that
it is getting tripped up in a constructor that I do not have and that
I am not allowed to have. I wonder if the error message is simply
wrong and it is really referring to .cctor (a class constructor) ?

At any rate, this is an awfully simple little compiland and I have no
idea how to make it fly in C++/CLI. I'm surprised to have my syntax
porting effort hung up on such simple things.

I assume that if you get rid of the global typedef with the same name that
the code compiles, but for whatever reason, you're stuck with having
multiple definitions of this name?

-cd
 
B

Bern McCarty

Yes. I am stuck with both the LevelID alias in the global namespace and with
reusing that identifier for the managed class in another namespace. If I
can produce the class with MEC++, then I should be able to produce the same
class with C++/CLI shouldn't I?

Can anyone see how? The examples I provided are very small and easy to try
out/tinker with.
 
G

Gary Chang[MSFT]

Hi Bern,

I already consulted this problem with our prodcut team, if there isn't any
specific reason to use the static_cast, we suggest you can change the
following line

public: initonly static Test::LevelID ApplicationInfo =
static_cast<Test::LevelID>(20u);

to

public: initonly static Test::LevelID ApplicationInfo =
(Test::LevelID)(20u);


Thanks!

Best regards,

Gary Chang
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Bern McCarty

Thanks Gary. I think that recommendation will get me by.

This is a compiler bug it not? The LevelID class has explicit conversion
operators that should used successfully here I think.
Is this an acknowledged problem with the compiler or is it considered right
and proper that reinterpret_cast is necessary to produce this class?

I find it very odd that I can produce this class with no cast operator whatsoever
when using the old syntax but to produce the class in the new syntax I not
only need to cast, but I need to get out the big gun: reinterpret_cast.
A mere static_cast is insufficient.

-Bern
 
G

Gary Chang[MSFT]

Thanks for the response, Bern.

I am afraid this seems to be a compiler issue, the C++/CLI has many
difference from the MEC++, so its complier behaves different from the
VC2003. I will forward this issue to our corresponding product team for
review.

Good Luck!

Best regards,

Gary Chang
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

Ben Voigt

Bern McCarty said:
Thanks Gary. I think that recommendation will get me by.

This is a compiler bug it not? The LevelID class has explicit conversion
operators that should used successfully here I think.
Is this an acknowledged problem with the compiler or is it considered
right and proper that reinterpret_cast is necessary to produce this class?
I find it very odd that I can produce this class with no cast operator
whatsoever when using the old syntax but to produce the class in the new
syntax I not only need to cast, but I need to get out the big gun:
reinterpret_cast. A mere static_cast is insufficient.

Can you use constructor notation?

public: initonly static Test::LevelID ApplicationInfo(20u);
 

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