optional parameter in a template

Discussion in 'C++' started by Vladimir Jovic, Jul 19, 2010.

  1. 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
     
    Vladimir Jovic, Jul 19, 2010
    #1
    1. Advertising

  2. Vladimir Jovic

    Helge Kruse Guest

    "Vladimir Jovic" <> wrote in message
    news:i219lc$lg1$...
    > 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
     
    Helge Kruse, Jul 19, 2010
    #2
    1. Advertising

  3. * 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>
     
    Alf P. Steinbach /Usenet, Jul 19, 2010
    #3
  4. Alf P. Steinbach /Usenet wrote:
    > * 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
     
    Vladimir Jovic, Jul 19, 2010
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ahmed Moustafa
    Replies:
    6
    Views:
    69,862
    grizzleybear
    Apr 17, 2012
  2. Otto Wyss
    Replies:
    6
    Views:
    434
    Jeff Flinn
    Nov 9, 2004
  3. Replies:
    2
    Views:
    269
    Bruno Desthuilliers
    Oct 30, 2006
  4. C Barr Leigh
    Replies:
    12
    Views:
    504
    Bruno Desthuilliers
    Mar 8, 2007
  5. Stuart Redmann
    Replies:
    5
    Views:
    482
    Stuart Redmann
    Dec 14, 2007
Loading...

Share This Page