locked
Getting Type for Nullable<T> at compile time. RRS feed

  • Question

  • Is there a way to retrieve a Type object for the Nullable generic at compile time in C++/CLI? In C# this would be accomplished with typeof(Nullable<>).

     

    Nullable::typeid returns a Type object for the non-generic Nullable type. Nullable<>::typeid is clearly incorrect C++ and even crashes the compiler for me (VS2005 SP1). Using a typedef as an in-between doesn't work either as typedef generics are illegal.

     

    I can get this Type object at runtime, but I would prefer to have the compiler do this work.

     

    Are there ways to get a Type at compile time other than typeid? It appears that the compiler has a hard time with type names that are "overloaded" (don't know a better term for this) in a single namespace based on generic-ness.

     

    Thanks,

    Mike.

    Monday, October 29, 2007 8:20 PM

All replies

  • In ISO C++ the following construct works fine:

    template<class T>
    struct determine_type   //this will contain a typedef for any other type as Nullable<T>
    {
         typedef T    type;
    }


    template<class T>
    struct determine_type<Nullable<T> > //template overload to resolve types inside Nullable
    {
        typedef T      type;
    };


    so the code to strip the type out of Nullable

    typedef Nullable<SomeType>       nullable_type;


    //you might need a typename before if called from template code
    typedef /* typename */ determine_type<nullable_type>::type     type_inside_nullable;


    Good Luck,
    Ovanes

    P.S. I think this should work in C++/CLI as well.
    Tuesday, October 30, 2007 4:39 PM
  • Hi Ovanes,

    That technique works great for finding the type parameter to the Nullable generic. However, what I was looking for was a way to apply the typeid operator to the Nullable generic itself.

     

    All I could find in the C++/CLI spec (1st ed., Dec. 2005) for this issue was at the end of section 15.3.7:

    "outside of the body of a generic type definition, the ::typeid operator shall not be applied to the bare name of that type".

    They give the following example,

     

    Code Block

    generic

    ref class X {

    public:

    static void F() {

    Type^ t1 = T::typeid; // okay

    Type^ t2 = X<T>::typeid; // okay

    Type^ t3 = X::typeid; // okay

    }

    };

    int main() {

    Type^ t4 = int::typeid; // okay

    Type^ t5 = X<int>::typeid; // okay

    Type^ t6 = X::typeid; // error

    }

     

     

    But t6 compiles just fine in VS2005 and the result is what I would expect: a Type object that provides information about the generic definition for X.

     

    Getting a Type object for the Nullable generic at compile time is more difficult (impossible?) because there is a non-generic Nullable class also in the system namespace. For example,

     

    Code Block

    Type^ t1 = Nullable<int>::typeid->GetGenericTypeDefinition();

    Type^ t2 = Nullable::typeid;

    Console::WriteLine(t1->FullName); // prints System.Nullable`1

    Console::WriteLine(t2->FullName); // prints System.Nullable

     

    So I can get the Type object I'm looking for using GetGenericTypeDefinition, but I was hoping that the compiler would be able to do this work and I wouldn't need to rely on a method call at runtime.
    Tuesday, October 30, 2007 7:01 PM
  • The problem is Nullable itself is probably an incomplete type. In plain C++ you can not apply anything to it, since it is not a type until it is specialized with template parameter. You can not make an instance out of it unless it is not specialized or have a default parameter. I assume C++/CLI will not be different.

    You can probably do a trick by deriving you own nullable type from the system one but specifying a default parameter in the template argument list:

    template<class T=void>
    class MyNullable : public Nullable<T>
    {};

    At this point you can also call MyNullable<>, which produces a MyNullable<void>. I hope that helps you.


    Best Regards,
    Ovanes
    Tuesday, October 30, 2007 7:28 PM
  •  

    Unfortunately (or maybe not), generics aren't specialized at compile time like templates are. Generic types have their own type identity and are compiled into an assembly as "open types". When they're used a "constructed type" will be created by the runtime. Also, we can't derive from CLR value types and Nullable<T> is one.

     

    I'm looking to get a Type object at compile time describing the "open type" for Nullable<T>.

    Tuesday, October 30, 2007 8:14 PM
  • Ok, but if we get back to my previous sample with retrieving the types. Is there any way to overload a template with uncomplete (open) type Nullable?

    struct uncomplete_type {};
    template<class T>
    struct determine_type<Nullable>
    {
    typedef uncomplete_type    type;
    };


    //now you can make a function overload:

    template<class T>
    void foo(T const& t)
    {
       // do smth ....
    }


    void foo(uncomplete_type)
    {
       // do smth else....
    }


    The scond function is always preferred to template according to C++ specs. Probably that could work, but may be not, since if you say generics are specialized at runtime, you might calculate an uncomplete type where it becomes complete at runtime... But you could try.
    Wednesday, October 31, 2007 8:57 AM