Template class to enable transparent use of pointers or references

Discussion in 'C++' started by a, Mar 15, 2006.

  1. a

    a Guest

    Hi,

    I'm trying to create a helper class that will allow me to use a pointer or
    reference to a class without knowing if it is a pointer or reference.

    Conceptual example:

    //******************
    // class B has one public method f
    class B
    {
    public:
    void f()
    {
    }
    };

    // use a fictional class A to do the following

    B b;
    B* pb = &b;

    A<>( b ).f();
    A<>( pb ).f();
    //*********************

    What this should do is regardless of whether the A constructor receives a
    pointer or reference to B, and without having to specify the actual type in
    the template argument list, it will be able to call the method f in the same
    fashion, using the . operator in this example (or it could be ->)

    Here is my attempt at this, using 2 specialized member functions for
    reference and pointer types - see my comments below.

    //*******************
    // helper class A

    template< typename T > class A
    {
    private:
    T _t;

    public:
    A( T t )
    : _t( t )
    {
    }

    void f()
    {
    }
    };

    // specialized method that works for references to B
    template<> inline void A< B& >::f()
    {
    return _t.f();
    }

    // specialized method that works for pointers to B
    template<> inline void A< B* >::f()
    {
    return _t->f();
    }
    //****************

    This doesn't work the way I intended. In order for it to work, I have to
    specify the argument type in the template argument list, which defeats the
    purpose of having this automatically done by the compiler.

    A<B&>( b ).f();
    A<B*>( pb ).f();

    I was expecting that the compiler would be capable of determining the
    template argument type from the type of the value passed to the constructor
    (b, or pb).

    I would appreciate any help or ideas on this.

    Thanks,

    A
    a, Mar 15, 2006
    #1
    1. Advertising

  2. a

    Kai-Uwe Bux Guest

    a wrote:

    > Hi,
    >
    > I'm trying to create a helper class that will allow me to use a pointer or
    > reference to a class without knowing if it is a pointer or reference.


    Sounds like a bad idea. Why do you want to blur distinctions? Usually,
    loosing information is nod good.

    What is the underlying problem that you are trying to solve?

    > Conceptual example:
    >
    > //******************
    > // class B has one public method f
    > class B
    > {
    > public:
    > void f()
    > {
    > }
    > };
    >
    > // use a fictional class A to do the following
    >
    > B b;
    > B* pb = &b;
    >
    > A<>( b ).f();
    > A<>( pb ).f();
    > //*********************
    >
    > What this should do is regardless of whether the A constructor receives a
    > pointer or reference to B, and without having to specify the actual type
    > in the template argument list, it will be able to call the method f in the
    > same fashion, using the . operator in this example (or it could be ->)


    Probably, it has to be ->. After all, you cannot overload the dot-operator.
    I consider that a defect in the standard, but I abandoned hope that this
    will be fixed any time soon.

    > Here is my attempt at this, using 2 specialized member functions for
    > reference and pointer types - see my comments below.
    >
    > //*******************
    > // helper class A
    >
    > template< typename T > class A
    > {
    > private:
    > T _t;
    >
    > public:
    > A( T t )
    > : _t( t )
    > {
    > }
    >
    > void f()
    > {
    > }
    > };
    >
    > // specialized method that works for references to B
    > template<> inline void A< B& >::f()
    > {
    > return _t.f();
    > }
    >
    > // specialized method that works for pointers to B
    > template<> inline void A< B* >::f()
    > {
    > return _t->f();
    > }
    > //****************
    >
    > This doesn't work the way I intended. In order for it to work, I have to
    > specify the argument type in the template argument list, which defeats the
    > purpose of having this automatically done by the compiler.
    >
    > A<B&>( b ).f();
    > A<B*>( pb ).f();
    >
    > I was expecting that the compiler would be capable of determining the
    > template argument type from the type of the value passed to the
    > constructor (b, or pb).
    >
    > I would appreciate any help or ideas on this.


    What about something like:

    template < typename T >
    class ref_or_ptr {

    T * t_ptr;

    public:

    ref_or_ptr ()
    : t_ptr ( 0 )
    {}

    ref_or_ptr ( T & r )
    : t_ptr ( &r )
    {}

    ref_or_ptr ( T * p )
    : t_ptr ( p )
    {}

    T * operator-> ( void ) {
    return ( t_ptr );
    }

    T & operator* ( void ) {
    return ( *t_ptr );
    }

    T const * operator-> ( void ) const {
    return ( t_ptr );
    }

    T const & operator* ( void ) const {
    return ( *t_ptr );
    }

    }; // ref_or_ptr<>

    typedef ref_or_ptr< int > int_whatever;

    #include <iostream>

    int main ( void ) {
    int i = 5;
    int_whatever i_alias ( i );
    int* i_ptr = new int ( 7 );
    int_whatever ptr_alias ( i_ptr );
    std::cout << *i_alias << " " << *ptr_alias << '\n';
    }


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Mar 15, 2006
    #2
    1. Advertising

  3. a

    a Guest

    Thanks for your reply.

    > Sounds like a bad idea. Why do you want to blur distinctions? Usually,
    > loosing information is nod good.
    >


    In general, you are right, it's not the best idea. In my specific case it's
    actually quite important to implement this behavior.

    I'm building a C++ API that is quite complex but which must address the
    needs of a variety of users of all levels, many of whom are not familiar and
    get confused by pointers. Since the API must still pass pointers around, I'm
    trying to create a set of higher level and easier to use APIs based on
    macros and templates. In this specific case, objects of a class B can appear
    as reference or pointers, and I want the user to only see them as
    references.

    Yes, your solution works - thanks!

    A
    a, Mar 15, 2006
    #3
  4. a

    Axter Guest

    a wrote:
    > Hi,
    >
    > I'm trying to create a helper class that will allow me to use a pointer or
    > reference to a class without knowing if it is a pointer or reference.
    >
    > Conceptual example:
    >
    > //******************
    > // class B has one public method f
    > class B
    > {
    > public:
    > void f()
    > {
    > }
    > };
    >
    > // use a fictional class A to do the following
    >
    > B b;
    > B* pb = &b;
    >
    > A<>( b ).f();
    > A<>( pb ).f();
    > //*********************
    >
    > What this should do is regardless of whether the A constructor receives a
    > pointer or reference to B, and without having to specify the actual type in
    > the template argument list, it will be able to call the method f in the same
    > fashion, using the . operator in this example (or it could be ->)
    >
    > Here is my attempt at this, using 2 specialized member functions for
    > reference and pointer types - see my comments below.
    >
    > //*******************
    > // helper class A
    >
    > template< typename T > class A
    > {
    > private:
    > T _t;
    >
    > public:
    > A( T t )
    > : _t( t )
    > {
    > }
    >
    > void f()
    > {
    > }
    > };
    >
    > // specialized method that works for references to B
    > template<> inline void A< B& >::f()
    > {
    > return _t.f();
    > }
    >
    > // specialized method that works for pointers to B
    > template<> inline void A< B* >::f()
    > {
    > return _t->f();
    > }
    > //****************
    >
    > This doesn't work the way I intended. In order for it to work, I have to
    > specify the argument type in the template argument list, which defeats the
    > purpose of having this automatically done by the compiler.
    >
    > A<B&>( b ).f();
    > A<B*>( pb ).f();
    >
    > I was expecting that the compiler would be capable of determining the
    > template argument type from the type of the value passed to the constructor
    > (b, or pb).
    >
    > I would appreciate any help or ideas on this.
    >

    I'm not sure if this is what you're looking for, but check out the
    following class:
    template<typename T>
    class ZeroMemorySafe
    {
    private:
    template <typename TT> struct deref_t {typedef TT type_t;};
    template <typename TT> struct deref_t<TT*> {typedef typename
    deref_t<TT>::type_t type_t;};
    public:
    typedef typename deref_t<T>::type_t ref_t;
    typedef T type_t;
    void operator()(ref_t &t)
    {
    ZeroMemory(&t, sizeof(t));
    }
    void operator()(ref_t *t)
    {
    ZeroMemory(t, sizeof(*t));
    }
    };

    I use the above class with the following function:
    template<class T>
    void ZeroMemoryT(T& t)
    {
    ZeroMemorySafe<T>()(t);
    }

    Which allows the above function to work with pointer types, and
    reference type.


    ----------------------------------------------------------------------------------------
    David Maisonave
    http://axter.com

    Top ten member of C++ Expert Exchange:
    http://www.experts-exchange.com/Cplusplus
    ----------------------------------------------------------------------------------------
    Axter, Mar 15, 2006
    #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. Patrick
    Replies:
    1
    Views:
    638
  2. Roger Leigh
    Replies:
    8
    Views:
    415
    Karl Heinz Buchegger
    Nov 17, 2003
  3. Jonathan Bartlett
    Replies:
    3
    Views:
    427
  4. christopher diggins
    Replies:
    16
    Views:
    731
    Pete Becker
    May 4, 2005
  5. A L
    Replies:
    1
    Views:
    503
    Alf P. Steinbach /Usenet
    Aug 25, 2010
Loading...

Share This Page