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( ); }
}; 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.
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
"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
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".
"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>&); This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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". ...
|
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...
|
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...
|
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...
|
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...
|
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:...
|
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
|
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):
...
|
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>...
|
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...
|
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...
|
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...
|
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...
|
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...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
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....
|
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
|
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...
| |