Search code examples
visual-c++c++-cliclr

Visual C++ CLR : Using non-primitive data types as attributes


Using Visual C++ on Visual Studio 2013. Project Type : "CLR Empty Project"

I am trying to create a class that contains private attributes of data type std::string and std::array.

The compiler gives me the following error:

"a member of a managed class cannot be of a non-managed class type"

The research that I have conducted leads me to believe that CLR projects only allow the use of primitive data types as class attributes.
Unfortunately, I have been unable to find a fix for this.

The error is given in the .h file. I have copied the .h file below :

{
public:

PlayableSet();
~PlayableSet();

bool verifySolutionSet(std::string solution);

std::array<int, 5> getPlayableIntegers();
std::array<char, 4> getPlayableOperators();
std::string getPlayableString();
std::array<int, 9> getPlayableSetIntegerCount();
std::array<int, 4> getPlayableSetOperatorCount();

private:

const static std::array<char, 4> OPERATOR_ARRAY ;
std::array<int, 5> PlayableIntegers;
std::array<char, 4> PlayableOperators = { '+', '-' };
std::string PlayableString = "";
std::array<int, 9> PlayableSetIntegerCount;
std::array<int, 4> PlayableSetOperatorCount = { 1, 1 }; 
}

Note :

  • I have included both array and string
  • The error is shown for all of the private attributes.
  • PlayableOperators and PlayableSetOperatorCount are only initialised with their first two elements. This is intended.

Solution

  • My recommendation is that if you're going to write a managed class, write a managed class. If you're going to write an unmanaged class, write an unmanaged class.

    C++/CLI allows mixing of managed and unmanaged code, but there are limits. When writing the definition of a single class, you generally want to stick with one or the other.

    • If you're going to write a managed class, write a managed class.
      • If you're going to write this class as managed (public ref class foo), then it should use managed types for its data members. If you need to use unmanaged types to access the class, do the conversion to/from managed types in the accessor/mutator methods.
      • In this case, this would be System::String^ and either cli::array<int>^ foo = gcnew cli::array<int>(length) or List<int>^ foo = gcnew List<int>().
    • If you're going to write an unmanaged class, write an unmanaged class.
      • If you're going to write this class as unmanaged (class foo), then it should use unmanaged types for its data members.

    If you find yourself using the managed/unmanaged conversions all the time, perhaps you need to write your class as the other one. Or consider changing your class definition to split the responsibilities of the class into managed and unmanaged classes.