473,320 Members | 2,104 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

casting my smart pointer up and down

Hi there,

I am writing a smart pointer that is similar to the boost intrusive ptr.
I am trying to make it behave like a c++ pointer including the implicit
and explicit casting behaviour.
Below is the part more or less relevant to my problem.

Version 1 is fine for casting to a derived class, but it must be called
explicitly even though it is used to cast to a base class.

Version 2 is fine for implicitly casting to a base class, but will never
cast to a derived class

Version 3 is really bad. It will cast to a derived class implicitly,
which is not what I want.

I cannot use 1 and 2 the same time, or is there a workaround that makes
the compiler think of them as different members?

template<typename T>
class THE_API Ref
{
public:
Ref( void ) : _pObj( NULL ) { }
Ref( T* Source ) {_set( Source ); }
Ref( const Ref<T>& Source ) {_set( Source._pObj ); }

// Version 1. would cast only explicitly
template< typename CASTTYPE > explicit
Ref( const Ref<CASTTYPE>& Source )
{
_set( static_cast<T*>( Source.GetNativePtr( ) ) );
}

// Version 2. is implicit and performs an implicit cast
template< typename CASTTYPE >
Ref( const Ref<CASTTYPE>& Source )
{
_set( Source.GetNativePtr( ) );
}

// Version 3. is implicit but performs an explicit cast
template< typename CASTTYPE >
Ref( const Ref<CASTTYPE>& Source )
{
_set( static_cast<T*>( Source.GetNativePtr( ) ) );
}

template< typename CASTTYPE >
explicit
Ref( CASTTYPE* source )
{ // error C2440: Did you cast T* to Ref<Ref<T> > ?
_set( static_cast<T*>( source ) );
}

private:
void _dec( ) { if( _pObj ) if ( !(--(_pObj->_refCount) ) )
delete _pObj; }
void _inc( ) { if( _pObj ) ++(_pObj->_refCount); }
void _set( T* Ptr ) { _pObj = Ptr; _inc( ); }
};
Jul 22 '05 #1
5 3123
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote in message
news:cp**********@svr7.m-online.net...
// Version 1. would cast only explicitly
template< typename CASTTYPE > explicit
Ref( const Ref<CASTTYPE>& Source )
{
_set( static_cast<T*>( Source.GetNativePtr( ) ) );
}

// Version 2. is implicit and performs an implicit cast
template< typename CASTTYPE >
Ref( const Ref<CASTTYPE>& Source )
{
_set( Source.GetNativePtr( ) );
}

// Version 3. is implicit but performs an explicit cast
template< typename CASTTYPE >
Ref( const Ref<CASTTYPE>& Source )
{
_set( static_cast<T*>( Source.GetNativePtr( ) ) );
}


I like version 2 because it seems the safest, and allows for the usual
construct

Ref<Base> f() {
Ref<Derived> out(new Derived);
...
return out;
}

As for static_cast or dynamic_cast from the base to the derived class, with
ordinary pointers one writes

Derived * d = static_cast<Derived *>(b);

But static_cast and dynamic_cast cannot be overloaded. So you could add new
member functions. Eg.

template <class T>
class Ref {
public:
template <class U>
Ref<U> do_dynamic_cast() const {
return Ref<U>(dynamic_cast<U*>(GetNativePtr()));
}
};

Ref<Base> b = f();
Ref<Derived> d = b.template do_dynamic_cast<Derived>(b);
There might be better soultions with operator conversions, etc.
Jul 22 '05 #2
Siemel Naran wrote:
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote in message
news:cp**********@svr7.m-online.net...

// Version 1. would cast only explicitly
template< typename CASTTYPE > explicit
Ref( const Ref<CASTTYPE>& Source )
{
_set( static_cast<T*>( Source.GetNativePtr( ) ) );
}

// Version 2. is implicit and performs an implicit cast
template< typename CASTTYPE >
Ref( const Ref<CASTTYPE>& Source )
{
_set( Source.GetNativePtr( ) );
}

// Version 3. is implicit but performs an explicit cast
template< typename CASTTYPE >
Ref( const Ref<CASTTYPE>& Source )
{
_set( static_cast<T*>( Source.GetNativePtr( ) ) );
}

I like version 2 because it seems the safest, and allows for the usual
construct


it is as safe as 1. but both have a lack of capability.
1. is not able to cast to base implicitly ( but c++ pointer can do )
2. is not able to cast to derived class explicitly
( but c++ pointer can do )
And my golden goal is to achieve behaviour as close as possible to c++
pointer
Ref<Base> f() {
Ref<Derived> out(new Derived);
...
return out;
}
yes it does. This and any other cast to base is possible.
As for static_cast or dynamic_cast from the base to the derived class, with
ordinary pointers one writes

Derived * d = static_cast<Derived *>(b);
yes, thats what I want with it
Ref<Derived> d = static_cast<Ref<Derived> >( b );

I use my own RTTI and I can ask any object for its runtime type and
verify any IS A relation. I could even make the cast checked, and throw
an appropriate exception.

But static_cast and dynamic_cast cannot be overloaded. So you could add new
member functions. Eg.

template <class T>
class Ref {
public:
template <class U>
Ref<U> do_dynamic_cast() const {
return Ref<U>(dynamic_cast<U*>(GetNativePtr()));
}
};

Ref<Base> b = f();
Ref<Derived> d = b.template do_dynamic_cast<Derived>(b);
What is b.template? Sure you meant it like this?

Even though what you wrote is close to my goal. I already used folloing:

Ref< Base > b = d.as< Base >( );

This is using a template member function on the Ref-class.
It could also be used like a non-member template function.

Ref< Base > b = ref_cast< Base >( d );

Thats probably what you meant.
I must say that you led me back to a point where I have been, but forgot
in the meanwhile. If I make above method consistent all over the
project, I won't need to use the static_cast and it even writes shorter
and is nearly as descriptive as the static_cast.


There might be better soultions with operator conversions, etc.

So, if someone knows a way to get the last little step to make it really
like c++ pointers, go go go...

Ingo
Jul 22 '05 #3
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote in message
news:cpkrpg$9k7
Ref<Base> b = f();
Ref<Derived> d = b.template do_dynamic_cast<Derived>(b);
What is b.template? Sure you meant it like this?


It's required by the standard. It tells the compiler to parser to interpret
the < as the beginning of a template declaration rather than the less than
operator.
Ref< Base > b = ref_cast< Base >( d );

Thats probably what you meant.
Yes, that's good. By not using member functions, you don't have to use the
ugly .template syntax.
I must say that you led me back to a point where I have been, but forgot
in the meanwhile. If I make above method consistent all over the
project, I won't need to use the static_cast and it even writes shorter
and is nearly as descriptive as the static_cast.


There might be better soultions with operator conversions, etc.

So, if someone knows a way to get the last little step to make it really
like c++ pointers, go go go...

Ingo

Jul 22 '05 #4
Siemel Naran wrote:
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote in message
news:cpkrpg$9k7

Ref<Base> b = f();
Ref<Derived> d = b.template do_dynamic_cast<Derived>(b);

What is b.template? Sure you meant it like this?

It's required by the standard. It tells the compiler to parser to interpret
the < as the beginning of a template declaration rather than the less than
operator.


I have never seen such syntax before and I cannot imagine *what* it is.
Can you post the declaration of that function?
Especially wether it is a member function or not. Because you write "b"
two times in that line.

Ref< Base > b = ref_cast< Base >( d );

Thats probably what you meant.

Yes, that's good. By not using member functions, you don't have to use the
ugly .template syntax.


Does that mean your version was a member function? Why do you pass it
the b as an argument?

Also my other version that writes like:
Ref< Derived > d = b.as< Derived >( );

is quite direct, and works well without "b.template".
Jul 22 '05 #5
"Ingo Nolden" <in**********@SPAMrecurdyn.org> wrote in message
Siemel Naran wrote:
Ref<Base> b = f();
Ref<Derived> d = b.template do_dynamic_cast<Derived>(b);
BTW, I have one too many b's. Should have been
Ref<Derived> d = b.template do_dynamic_cast<Derived>();
I have never seen such syntax before and I cannot imagine *what* it is.
Can you post the declaration of that function?
template <class T> Ref {
public:
template <class U>
Ref<U> do_dynamic_cast() const;
};
Especially wether it is a member function or not. Because you write "b"
two times in that line.


Mistake on my part. There should be just one b.

Ref< Base > b = ref_cast< Base >( d );

Thats probably what you meant.

Yes, that's good. By not using member functions, you don't have to use the ugly .template syntax.


Does that mean your version was a member function? Why do you pass it
the b as an argument?

Also my other version that writes like:
Ref< Derived > d = b.as< Derived >( );

is quite direct, and works well without "b.template".


Right, it works on your compiler. But a fully conforming compiler is
supposed to reject it, because it does not know whether the < is the less
than sign or a template argument list. Most compilers I've worked with
figure it out in simple cases. So to be conformant, it should be

Ref< Derived > d = b.template as< Derived >( );

and it's exactly the same as my version, except for the function name.
So to avoid the ugly .template notation, you could use

template <class U, class T>
Ref<U> Ref_dynamic_cast(const Ref<T>&);
Jul 22 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: David B. Held | last post by:
I wanted to post this proposal on c.l.c++.m, but my news server apparently does not support that group any more. I propose a new class of exception safety known as the "smart guarantee". ...
16
by: He Shiming | last post by:
Hi, I'm having a little bit of trouble regarding pointer casting in my program. I don't understand why the following two cases produce different results. Case 1: IInterface *pInterface = new...
33
by: Ney André de Mello Zunino | last post by:
Hello. I have written a simple reference-counting smart pointer class template called RefCountPtr<T>. It works in conjunction with another class, ReferenceCountable, which is responsible for the...
9
by: Jess | last post by:
Hello, It seems both static_cast and dynamic_cast can cast a base class pointer/reference to a derived class pointer/reference. If so, is there any difference between them? In addition, if I...
54
by: Boris | last post by:
I had a 3 hours meeting today with some fellow programmers that are partly not convinced about using smart pointers in C++. Their main concern is a possible performance impact. I've been explaining...
5
by: johanatan | last post by:
Does anyone know the reasons for the lack of an implicit casting operator in any greater depth than: A. Automatic conversion is believed to be too error prone. (from the FAQ at the bottom of:...
9
by: Taras_96 | last post by:
Hi everyone, I was experimenting with static_cast and reinterpret cast #include <iostream> struct A1 { int a; }; struct A2 { double d; }; struct B : public A1, A2
50
by: Juha Nieminen | last post by:
I asked a long time ago in this group how to make a smart pointer which works with incomplete types. I got this answer (only relevant parts included): ...
4
by: Wally Barnes | last post by:
Can someone help a poor C++ programmer that learned the language before there was a standard lib .. etc ? Basically I have two classes that look something like below: template <class T>...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.