Automatic casting of template object to template pointer in c++ - c++

I have a URes class which contains a single pointer to <T>, with indirection operators -> and * overloaded so I can use the instance as a pointer directly.
However I also want to be able to pass my URes instance to functions that normally take the pointer inside the URes instance.
How do I make it so that when my URes instance object is passed to a function it is automatically cast to the pointer it contains?

The same way that you create any outbound conversion: by declaring and defining an operator.
In this case, you want a member operator T*.
Example:
template <typename T>
struct Foo {
operator T*() {
return 0;
}
};
void bar(int* p) {}
int main() {
Foo<int> f;
bar(f);
}
However, I'd recommend avoiding this and implementing a member T* get() instead. It should be an explicit step for a calling scope to obtain a pointer from your object.

You can do that by providing a conversion operator from that class to the pointer-type:
class Foo {
public:
operator int() const { // enables implicit conversion from Foo to int
}
};
Note that such implicit conversion can introduce unexpected behavior.

Related

Overload arrow operator as ref qualified

If the arrow operator of my class returns a pointer to internal data, is it a good idea to always declare it as ref qualified and have it work solely for l-values?
template <class T>
class Dummy
{
T _data; // data lives within the class
public:
Dummy() { /* some ctor logic */ }
T* operator->() & { return &_data; }
// ^ this is the question
T const* operator->() const& { return &_data; }
// ^ this is the question
};
The reasoning behind this, is that using the arrow operator on a temporary instance would create a dangling pointer by default, since the data lives in my class.
Also, is there a canonical resource on ref qualifiers and overloading member access operators?
Note that the provided class example is purely for demo reasons, to provide a minimum example.

Remove ambiguity in function call on implicitly converted smart pointer

I'm reading item 28 on smart pointers of Scott Meyers's More Effective C++ and have the following question.
A complete demonstration can be found at http://ideone.com/aKq6C0 .
A derived class pointer can be converted implicitly to a base class pointer:
class Base {};
class Derived : public Base {};
void foo(Base* b) { cout << "foo called on Base pointer" << endl;}
Derived *d = new Derived();
foo(d); //No problem
But such implicit conversion cannot happen for smart pointers, i.e. SmartPtr<Derived> cannot be implicitly converted to SmartPtr<Base>. So we use a member template for such conversions:
template<typename T>
class SmartPtr {
public:
//constructors, operator->, etc
//member template for type conversion
template<NewType>
operator SmartPtr<NewType> () {
return SmartPtr<NewType>(pointee);
}
private:
T* pointee;//the raw pointer
};
This can almost work, but it can cause ambiguity:
class Remote {};
class Base : public Remote {};
class Derived : public Base {};
void foo(const SmartPtr<Remote>& p) { cout << "remote" << endl;}
void foo(const SmartPtr<Base>& p) { cout << "base" << endl;}
SmartPtr<Derived> d(new Derived());
foo(d);//compile error: ambiguity
In this example, the compiler does not know whether it should convert d to SmartPtr<Base> or SmartPtr<Remote>, although for a raw pointer Base is apparently superior. The book says
The best we can do is to use member templates to generate conversion functions, then use casts in those cases where ambiguity results.
But how exactly do we apply cast here? foo(static_cast<SmartPtr<Base>>(d)) does not compile either. From the error message I can tell that the error comes from the use of non-const reference in the copy-constructor of SmartPtr. I'm wondering what's the correct way to make the function call.
//constructors
This is the most important part that you have omitted :)
Your cast is correct as such, it all depends on set of constructors you have. If you have one that takes non-const ref - you would get the error you mentioned, if you can just change ref to being const in copy ctor and code would compile.
It may be not very obvious, but when you call
return SmartPtr<NewType>(pointee);
you are constructing new SmartPtr<NewType> that have to accept T*, and NewType and T are different types. Most likely you only have ctor that accepts raw pointer of same type (i.e. T* for SmartPtr<T> and X* for SmartPtr<X>) so compiler is looking for another converting ctor to create your new SmartPtr and finds your copy ctor, but it can't bind new value to non const ref
Edit:
IF you are using c++11 adding move ctor would also solve your problem as it would be able to bind to rvalue
SmartPtr( SmartPtr<T>&& other): pointee(other.pointee) { other.pointee = nullptr; }

Explicit modifier for constructors taking reference argument

I read that it's a good practice to define single argument constructors explicit in order to avoid implicit conversions. I understand the pitfall of having int value promoted to class object. I wonder if it also applies to the constructors accepting reference types. How one can provoke implicit conversion in this case:
class Foo
{
public:
Foo(Bar& bar) { }
};
Does the situation changes if the constructor accepts pointers, is conversion from NULL and nullptr possible ?
class Foo
{
public:
Foo(Bar* bar) { }
};
Yes to both. A function with signature
void acceptFoo(const Foo& foo)
will make the compiler to create a Foo if you pass a Bar there.
Same for 0 and nullptr.

Templated conversion operator in a template class with default constructor?

I want a templated class with a templated conversion operator and a default constructor, but my initial attempt isn't working.
template<typename T>
class C
{
public:
C() {}
template<typename U>
operator U()
{
C<U> c; // (*)
c._a = dynamic_cast<U*>(_a);
return c;
}
private:
T* _a;
};
But now, when I try to create an instance of C,
template<typename T>
void F()
{
...
C<T> obj;
}
operator U() keeps calling itself over and over at (*), eventually segfaulting. The same thing happens when I define the function that does the casting externally and call it from operator U()--in which case there is no call to C::C() from within the class definition.
It seems to me then that the conversion operator is getting called when I want the default constructor called--it is essentially trying to convert itself. But surely, there's a way to do what I'm trying to do?
Note that in operator X (where X is a type) functions, you should usually return something of type X. You're returning a C<U> when you're trying to convert the invoking object to a U which causes the following to happen:
int a = someC; (where someC is a C of any type) will try to assign a C<X> to an int
operator T<int> will be called on someC which will return a C<int> and then try to assign it to an int
operator T<int> will be called on the aforementioned return value which will return a C<int>
That return value which is a C<int> will attempt to be converted to an int which will call operator T<int>....
goto 3;
Hopefully you can see why the infinite recursion and subsequent stack overflow occurs.
You cannot return a C<U> from operator T<U> of class C. You need to redesign your class if you need to for some reason.

C++ covariant templates

I feel like this one has been asked before, but I'm unable to find it on SO, nor can I find anything useful on Google. Maybe "covariant" isn't the word I'm looking for, but this concept is very similar to covariant return types on functions, so I think it's probably correct. Here's what I want to do and it gives me a compiler error:
class Base;
class Derived : public Base;
SmartPtr<Derived> d = new Derived;
SmartPtr<Base> b = d; // compiler error
Assume those classes are fully fleshed out... I think you get the idea. It can't convert a SmartPtr<Derived> into a SmartPtr<Base> for some unclear reason. I recall that this is normal in C++ and many other languages, though at the moment I can't remember why.
My root question is: what is the best way to perform this assignment operation? Currently, I'm pulling the pointer out of the SmartPtr, explicitly upcasting it to the base type, then wrapping it in a new SmartPtr of the appropriate type (note that this is not leaking resources because our home-grown SmartPtr class uses intrusive reference counting). That's long and messy, especially when I then need to wrap the SmartPtr in yet another object... any shortcuts?
SmartPtr<Base> and SmartPtr<Derived> are two distinct instantiations of a the SmartPtr template. These new classes do not share the inheritance that Base and Derived do. Hence, your problem.
what is the best way to perform this assignment operation?
SmartPtr<Base> b = d;
Does not invoke assignment operator. This invokes the copy-ctor (the copy is elided in most cases) and is exactly as if you wrote:
SmartPtr<Base> b(d);
Provide for a copy-ctor that takes a SmartPtr<OtherType> and implement it. Same goes for the assignment operator. You will have to write out the copy-ctor and op= keeping in mind the semantics of SmartPtr.
Both the copy constructor and the assignment operator should be able to take a SmartPtr of a different type and attempt to copy the pointer from one to the other. If the types aren't compatible, the compiler will complain, and if they are compatible, you've solved your problem. Something like this:
template<class Type> class SmartPtr
{
....
template<class OtherType> SmartPtr(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> copy constructor
template<class OtherType> SmartPtr<Type> &operator=(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> assignment operator
};
Templates are not covariant, and that's good; imagine what would happen in the following case:
vector<Apple*> va;
va.push_back(new Apple);
// Now, if templates were covariants, a vector<Apple*> could be
// cast to a vector<Fruit*>
vector<Fruit*> & vf = va;
vf.push_back(new Orange); // Bam, we just added an Orange among the Apples!
To achieve what you are trying to do, the SmartPointer class must have a templatized constructor, that takes either another SmartPointer or a pointer of another type. You could have a look at boost::shared_ptr, which does exactly that.
template <typename T>
class SmartPointer {
T * ptr;
public:
SmartPointer(T * p) : ptr(p) {}
SmartPointer(const SmartPointer & sp) : ptr(sp.ptr) {}
template <typename U>
SmartPointer(U * p) : ptr(p) {}
template <typename U>
SmartPointer(const SmartPointer<U> & sp) : ptr(sp.ptr) {}
// Do the same for operator= (even though it's not used in your example)
};
Depends on the SmartPtr class. If it has a copy constructor (or in your case, assignment operator) that takes SmartPtr<T>, where T is the type it was constructed with, then it isn't going to work, because SmartPtr<T1> is unrelated to SmartPtr<T2> even if T1 and T2 are related by inheritance.
However, if SmartPtr has a templatized copy constructor/assignment operator, with template parameter TOther, that accepts SmartPtr<TOther>, then it should work.
Assuming you have control of the SmartPtr class, the solution is to provide a templated constructor:
template <class T>
class SmartPtr
{
T *ptr;
public:
// Note that this IS NOT a copy constructor, just another constructor that takes
// a similar looking class.
template <class O>
SmartPtr(const SmartPtr<O> &src)
{
ptr = src.GetPtr();
}
// And likewise with assignment operator.
};
If the T and O types are compatible, it will work, if they aren't you'll get a compile error.
I think the easiest thing is to provide automatic conversion to another SmartPtr according to the following:
template <class T>
class SmartPtr
{
public:
SmartPtr(T *ptr) { t = ptr; }
operator T * () const { return t; }
template <class Q> operator SmartPtr<Q> () const
{ return SmartPtr<Q>(static_cast<Q *>(static_cast<T *>(* this))); }
private:
T *t;
};
Note that this implementation is robust in the sense that the conversion operator template does not need to know about the semantics of the smart pointer, so reference counting does not need to replicated etc.