Friday, April 15, 2011

Use C++ CLI template class in C#

Hi,

I have the following class in C++/CLI and an explicit template instantiation for the int primitive..

template<typename T>
public ref class Number
{
    T _value;
public:
    static property T MinValue
    {
        T get()
        {
            return T::MinValue;
        }
    }

    static property T MaxValue
    {
        T get()
        {
            return T::MaxValue;
        }
    }

    property T Value
    {
        T get()
        {
            return _value;
        }

        void set(T value)
        {
            if( value<MinValue || value > MaxValue)
                throw gcnew System::ArgumentException("Value out of range");

            _value = value;
        }
    }

};

template ref class Number<int>;

On compiling this and inspecting the generated assembly using reflector I am able to see a class called Number<int> but while trying to instantiate this same class in C# the compiler complains about some System::Number class not taking a template argument. What am I doing wrong? Can this be done at all?

From stackoverflow
  • I have a work around, declare an additional class inheriting the Number<int> class. This class is now visible in C# and can be instantiated.

    public ref class MyInt32 : public Number<int>
    {
    };
    
  • If your goal is to create a parametrized type in C++ CLI, and then use that type from C#, I think that you need to create a generic type rather than a template type (see Stan Lippman's Blog for the reasons why both methods exist). See here for information on how to create generic types in C++ CLI.

    SDX2000 : Sadly, creating generic types defeats the whole purpose of using C++/CLI since C# can do the same and is equally ineffective.
    Andy : Then it sounds like the answer you posted is the only way to go (even though that somewhat defeats the purpose of using templates, too). As @JaredPar said, templates are not the same as generics, and only C++ can use templates.
  • Reflector is lying a little bit here. The name of the class is not actually Number<int>. It is actually 'Number<int>'. Notice the single quotes. These are only visible when you view the type name with ildasm.

    I believe this is done to make the type unbindable in most languages as they have no way of understanding how a C++ template actually works. This makes it effectively only visible to the C++ compiler which is appropriate since it's the only MS compiler that actually supports templates (templates != generics).

    Anton Tykhyy : And I think that C++/CLI templates have a required modifier on them as well, ildasm should show that as well. CLI prohibits tools who don't understand a required modifier to use the member.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.