Template class to enable transparent use of pointers or references

A

a

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
 
K

Kai-Uwe Bux

a said:
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
 
A

a

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

Axter

a said:
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
----------------------------------------------------------------------------------------
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top