Search code examples
c++visual-studiotemplatesboosttype-traits

isAbstract template and visual studio


The following template will decide if T is abstract with g++.

/**
   isAbstract<T>::result is 1 if T is abstract, 0 if otherwise.
 */
template<typename T>
class isAbstract
{
   class No { };
   class Yes { No no[3]; }; 

   template<class U> static No test( U (*)[1] ); // not defined
   template<class U> static Yes test( ... ); // not defined 

public:
   enum { result = sizeof( isAbstract<T>::template test<T>( 0 ) ) == sizeof(Yes) }; 
};

For example: struct myClass2 { virtual void f() {} }; struct myClass1 { virtual void f() = 0; };

bool twoAbstract = isAbstract<myClass2>::result;
bool oneAbstract = isAbstract<myClass1>::result;

However, it fails in visual studio 9.0 with the error:

error C2784: 'AiLive::isAbstract<T>::No AiLive::isAbstract<T>::test(U (*)[1])' : could not deduce template argument for 'U (*)[1]' from 'myClass2'

Does anyone have an idea of what the problem is and how to fix this?

MSDN Reports that they now have an is_abstract class since VS2008 as part of TR1 (inside the header type_traits). However, it seems to be missing from my installation.

PS. For reasons that are long and boring, I can't reimplement this via Boost.

Update

Also, tried replacing,

template<class U> static No test( U (*)[1] ); 

with each of,

template<class U> static No test( U (*x)[1] );
template<class U> static No test( U (*)() );
template<class U> static No test( U (*x)() );

and

template <typename U>
struct U2 : public U
{
   U2( U* ) {}
};

// Match if I can make a U2
template <typename U> static No test( U2<U> x  );

and

// Match if I can make a U2
template <typename U> static No test( U2<T> x  );

No luck - all say that template argument cannot be deduced for U.


Solution

  • This works for me in VC9:

    template<typename T>
    class isAbstract
    {
        class No { };
        class Yes { No no[3]; }; 
    
        template<class U> static No test( U (*)[1] ); // not defined
        template<class U> static Yes test( ... ); // not defined 
    
    public:
        enum { result = sizeof( test<T>( 0 ) ) == sizeof(Yes) }; 
    };
    

    Notice I just had to remove isAbstract<T>:: from the call to test.