optional parameter in a template

V

Vladimir Jovic

Hello,

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?
Is there a way to make the above example compile?

Thank in advance
 
H

Helge Kruse

Vladimir Jovic said:
Hello,

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
....

Is there a way to typedef type2 in the class MyClass as void, if it not
defined in the template parameter?

Add the class myA and use it instead of class A.


class myA : public A
{
public:
typedef void type2;
};

int main()
{
MyClass< B > c1;
MyClass< myA > c2;
}


Helge
 
A

Alf P. Steinbach /Usenet

* 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)
 
V

Vladimir Jovic

Alf said:
* Vladimir Jovic, on 19.07.2010 12:33:
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>


Although the Helge's solution is nice, this is actually what I was
looking for.

Thank you
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top