* Vladimir Jovic, on 19.07.2010 12:33:
>
> Next example :
>
> // code
> class A
> {
> public :
> typedef int type1;
> };
> class B
> {
> public :
> typedef int type1;
> typedef int type2;
> };
>
> template < typename T >
> class MyClass
> {
> typedef typename T::type1 type1;
> typedef typename T::type2 type2;
> };
>
> int main()
> {
> MyClass< B > c1;
> MyClass< A > c2;
> }
> // !code
>
> should give next errors when compiled :
> g++ s.cpp
> s.cpp: In instantiation of ‘MyClass<A>’:
> s.cpp:26: instantiated from here
> s.cpp:20: error: no type named ‘type2’ in ‘class A’
>
>
>
> In my real code, class MyClass is my class, and I can change it, but I
> can not change classes A and B. There are more classes with different
> number of typedefs, but they all have the same pattern (similar to above) :
> class D
> {
> public :
> typedef int type1;
> typedef int type2;
> typedef int type3;
> typedef int type4;
> };
>
> Is there a way to typedef type2 in the class MyClass as void, if it not
> defined in the template parameter?
Yes.
> Is there a way to make the above example compile?
Helge Kruse's reply else-thread, deriving from the classes, may be the most
practical.
But if it's impractical to derive, e.g. lots of constructors, then e.g. a bit of
SFINAE (Substitution Failure Is Not An Error for template argument),
<code>
#include <iostream>
#include <typeinfo>
class A
{
public :
typedef int type1;
};
class B
{
public :
typedef int type1;
typedef int type2;
};
namespace detail{
typedef char YesType;
typedef struct { char x[2]; } NoType;
template< class U, int >
struct Type1
{
typedef void T;
};
template< class U >
struct Type1< U, sizeof( YesType ) >
{
typedef typename U::type1 T;
};
template< class U, int >
struct Type2
{
typedef void T;
};
template< class U >
struct Type2< U, sizeof( YesType ) >
{
typedef typename U::type2 T;
};
template< class T >
class TypesOf
{
private:
template< class U >
static YesType hasType1( typename U::type1 const* );
template< class U >
static NoType hasType1( ... );
template< class U >
static YesType hasType2( typename U::type2 const* );
template< class U >
static NoType hasType2( ... );
public:
typedef typename Type1< T, sizeof( hasType1<T>( 0 ) ) >::T T1;
typedef typename Type2< T, sizeof( hasType2<T>( 0 ) ) >::T T2;
};
} // namespace detail
template < typename T >
class MyClass
{
public:
typedef typename detail::TypesOf< T >::T1 type1;
typedef typename detail::TypesOf< T >::T2 type2;
};
int main()
{
MyClass< B > c1;
MyClass< A > c2;
std::cout << typeid( MyClass< A >::type1 ).name() << std::endl;
std::cout << typeid( MyClass< A >::type2 ).name() << std::endl;
}
</code>
Cheers & hth.,
- Alf (intricate kludge creation mood)
--
blog at <url: http://alfps.wordpress.com>
|