Copy constructor with smart pointer - c++

I have a class with one std::unique_ptr as class member. I was wondering, how to correctly define the copy constructor, since I'm getting the following compiler error message: error C2248: std::unique_ptr<_Ty>::unique_ptr : cannot access private member declared in class 'std::unique_ptr<_Ty>. My class design looks something like:
template <typename T>
class Foo{
public:
Foo(){};
Foo( Bar<T> *, int );
Foo( const Foo<T> & );
~Foo(){};
void swap( Foo<T> & );
Foo<T> operator = ( Foo<T> );
private:
std::unique_ptr<Bar> m_ptrBar;
int m_Param1;
};
template < typename T >
Foo<T>::Foo( const Foo<T> & refFoo )
:m_ptrBar(refFoo.m_ptrBar),
m_Param1(refFoo.m_Param1)
{
// error here!
}
template < typename T >
void Foo<T>::swap( Foo<T> & refFoo ){
using std::swap;
swap(m_ptrBar, refFoo.m_ptrBar);
swap(m_Param1, refFoo.m_Param1);
}
template < typename T >
Foo<T> Foo<T>::operator = ( Foo<T> Elem ){
Elem.swap(*this);
return (*this);
}

Assuming the goal is to copy-construct the uniquely-owned Bar,
template < typename T >
Foo<T>::Foo( const Foo<T> & refFoo )
: m_ptrBar(refFoo.m_ptrBar ? new Bar(*refFoo.m_ptrBar) : nullptr),
m_Param1(refFoo.m_Param1)
{
}

Unique_ptr documentation:
Stores a pointer to an owned object. The object is owned by no other unique_ptr.
The object is destroyed when the unique_ptr is destroyed.
You cant copy it because two objects can't own it.
Try switching to a std::shared_ptr.
EDIT I should point out that this would make both objects have a pointer to that same object. If you want to copy the uniquely owned object Cubbi's solution is the correct one.

A possibility is to create a new clone_ptr type for this.
Below is a rudimentary example of a clone_ptr that invokes the correct copy constructor (and destructor) of a derived object. This is done here by creating a "type erasure" helper when the clone_ptr is created.
Other implementations may be found on the Internet.
#include <memory>
namespace clone_ptr_detail
{
template <class T>
class clone_ptr_helper_base
{
public:
virtual ~clone_ptr_helper_base() {}
virtual T* clone(const T* source) const = 0;
virtual void destroy(const T* p) const = 0;
};
template <class T, class U>
class clone_ptr_helper: public clone_ptr_helper_base<T>
{
public:
virtual T* clone(const T* source) const
{
return new U(static_cast<const U&>(*source));
}
virtual void destroy(const T* p) const
{
delete static_cast<const U*>(p);
}
};
}
template <class T>
class clone_ptr
{
T* ptr;
std::shared_ptr<clone_ptr_detail::clone_ptr_helper_base<T>> ptr_helper;
public:
template <class U>
explicit clone_ptr(U* p): ptr(p), ptr_helper(new clone_ptr_detail::clone_ptr_helper<T, U>()) {}
clone_ptr(const clone_ptr& other): ptr(other.ptr_helper->clone(other.ptr)), ptr_helper(other.ptr_helper) {}
clone_ptr& operator=(clone_ptr rhv)
{
swap(rhv);
return *this;
}
~clone_ptr()
{
ptr_helper->destroy(ptr);
}
T* get() const { /*error checking here*/ return ptr; }
T& operator* () const { return *get(); }
T* operator-> () const { return get(); }
void swap(clone_ptr& other)
{
std::swap(ptr, other.ptr);
ptr_helper.swap(other.ptr_helper);
}
};
See usage example: http://ideone.com/LnWa3
(But perhaps you don't really need to copy your objects, and might rather explore the possibilities of move semantics. For example, you can have a vector<unique_ptr<T>>, as long as you don't use functions that copy the contents.)

Related

Is there a "dynamic decltype"?

This question is related to decltype and multiple inheritance.
Assume I have the following:
an abstract class A with a few virtual methods,
a few derived classes that implement methods using the previous virtual ones (each of these classes is a sort of use-case),
a final concrete class that inherits from a subset of the previous use-cases and implements the pure virtual methods.
For example:
#include <iostream>
/**
* "Iterable container"
*/
template <class T>
struct A
{
virtual T* data() =0;
virtual const T* data() const =0;
virtual unsigned size() const =0;
T* begin() { return data(); }
T* end() { return data()+size(); }
const T* begin() const { return data(); }
const T* end() const { return data()+size(); }
};
// ------------------------------------------------------------------------
/**
* Iterative assignment
*/
template <class T>
struct B: public A<T>
{
auto operator =( const T& val ) -> decltype(*this)
{
for ( auto& v: *this ) v = val;
return *this;
}
};
/**
* Iterative display
*/
template <class T>
struct C: public A<T>
{
void show() const
{
for ( auto& v: *this )
std::cout<< v << " ";
std::cout<< std::endl;
}
};
// ------------------------------------------------------------------------
/**
* Concrete implementation
*/
template <class T, unsigned N>
struct D:
public B<T>,
public C<T>
{
using B<T>::operator=;
T dat[N];
T* data() { return dat; }
const T* data() const { return dat; }
unsigned size() const { return N; }
};
// ------------------------------------------------------------------------
int main()
{
D<double,5> d;
(d = 42).show(); // compile-time error, "no member named 'show' in 'B<double>'"
}
The problem is this (no pun intended); if one of the "use-case" method should return a reference to *this, I would like this to be a reference to the final concrete class, so that I could chain the call with other methods from other use-cases.
With the previous implementation however, I'm getting a compile-time error. Is there another way to achieve what I explained?
The solution is to use CRTP; you tell B to return an lvalue reference to D<T, N> by passing the most derived type as an additional template parameter.
template <class T, class Derived>
struct B: public A<T>
{
auto operator =( const T& val ) -> Derived&
// ...
template <class T, unsigned N>
struct D:
public B<T, D<T, N>>,
// ...
You can give D an overriding operator= that returns a D &:
auto operator =( const T& val ) -> decltype(*this) override
{
B<T>::operator=(val);
return *this;
}
This works because D & is covariant with B &, and overriding functions must have a covariant return type. This currently shadows B's operator=, too, because that one is not virtual.

Template specialization with a specific templated class

Given the following simple C++ class:
using namespace std;
template<class T1>
class ValueWrapper {
private:
T1 value_;
public:
ValueWrapper() {}
ValueWrapper(const T1& value) {
value_ = value;
}
ValueWrapper(const ValueWrapper<T1> &wrapper) {
value_ = wrapper.value_;
}
ValueWrapper& Set(const T1& value) {
value_ = value;
return *this;
}
T1 Get() const {
return value_;
}
};
I was trying to create a simple shared_ptr wrapper for that class (ultimately allowing the developer to use the class without the dereferencing operator if desired). While I've seen a few examples of wrapping a shared_ptr, I couldn't find any that also used a specialization for a templated class.
Using the class above, I created a ValueShared class which derives from shared_ptr:
template<class T1>
class ValueShared : public shared_ptr<T1> {
public:
ValueShared& operator =(const T1& rhs) {
// nothing to do in base
return *this;
}
};
Then, I created a custom make_shared_value function:
//
// TEMPLATE FUNCTION make_shared
template<class T1, class... Types> inline
ValueShared<T1> make_shared_value(Types&&... Arguments)
{ // make a shared_ptr
_Ref_count_obj<T1> *_Rx = new _Ref_count_obj<T1>(_STD forward<Types>(Arguments)...);
ValueShared<T1> _Ret;
_Ret._Resetp0(_Rx->_Getptr(), _Rx);
return (_Ret);
}
But, here's the problem code:
template<class T1, class ValueWrapper<T1>>
class ValueShared<ValueWrapper<T1>> : public shared_ptr<ValueWrapper<T1>>{
public:
ValueShared& operator =(const ValueWrapper<T1>& rhs) {
auto self = this->get();
self.Set(rhs->Get());
return *this;
}
};
I wanted to provide a specialization of the equals operator here that was specialized to the ValueWrapper class (so that it would Get/Set the value from the right hand side value).
I've tried a few things, but the current error is:
error C2943: 'ValueWrapper<T1>' : template-class-id redefined
as a type argument of a template
Maybe this isn't the proper approach, or maybe it's not possible?
Following should remove your error:
template<class T1>
class ValueShared<ValueWrapper<T1>> : public shared_ptr<ValueWrapper<T1>> {
public:
ValueShared& operator =(const ValueWrapper<T1>& rhs)
{
auto self = this->get();
self->Set(rhs.Get());
return *this;
}
};

How can I modify my boost::any like class

I'm trying to implement boost::any like class:
struct any
{
private:
struct holderBase
{
virtual ~holderBase(){}
};
template<typename T>
struct holder : public holderBase
{
T content;
holder(const T& value) : content(value){}
holder(const holder<T>& other) : content(other.content){}
};
holderBase *hl;
public:
template<typename T>
any(const T& data = T()) { hl = new holder<T>(data); }
any(const any& other) { hl = other.hl; }
template<typename T>
T get()
{
if(holder<T>* p_hl = dynamic_cast<holder<T>*>(hl))
return p_hl->content;
else
throw std::runtime_error("std::runtime_error");
}
};
I use a holder class (inherited by holderBase) to store the data.
How can I modify the any::get() function (or even modify the whole code) so that it doesn't need a template parameter (the get() function)?
You could do it like this:
template<typename T>
T get(T *ptr);
Similar to the C time function, you would return the result, as well as store it in ptr.
Edit: You could also override the casting operator:
template<typename T>
operator T()
{
return get<T>();
}
Which will implicitly do what you want.
Stating the obvious: If you don't want to return 1 particular type to the user then it needs to be templated. There's nothing you can do about it.

C++ -- why we have to define this friend template class

template<class T>
class auto_ptr2 {
public:
explicit auto_ptr2(T *p = 0): pointee(p) {}
template<class U>
auto_ptr2(auto_ptr2<U>& rhs): pointee(rhs.release()) {}
~auto_ptr2() { delete pointee; }
template<class U>
auto_ptr2<T>& operator=(auto_ptr2<U>& rhs)
{
if (this != &rhs) reset(rhs.release());
return *this;
}
T& operator*() const { return *pointee; }
T* operator->() const { return pointee; }
T* get() const { return pointee; }
T* release()
{
T *oldPointee = pointee;
pointee = 0;
return oldPointee;
}
void reset(T *p = 0)
{
if (pointee != p) {
delete pointee;
pointee = p;
}
}
private:
T *pointee;
//template<class U> friend class auto_ptr2<U>;
// Question 1> Why we have to define this friend class
// Question 2> I cannot compile this code with above line with VS2010.
// Error 1 error C3772: 'auto_ptr2<T>' : invalid friend template declaration
};
thank you
Why we have to define this friend class
I'm fairly sure you don't; as far as I can see, nothing is referencing the private member of a different template instantiation. You would need it if the copy constructor or assignment operator manipulated rhs.pointee directly, rather than just calling rhs.release().
I cannot compile this code with above line with VS2010.
The declaration should be:
template<class U> friend class auto_ptr2;

How to implement smart pointer which can be instantiated with void?

Some smart pointer templates, such as boost::shared_ptr, may be instantiated with void to hold an arbitrary object:
http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/sp_techniques.html#pvoid
Below is a minimal scoped_ptr implementation. When instantiated with void, the compiler complains about an illegal "reference to void" being formed in the dereference operator. It seems the "substitution failure is not an error" (SFINAE) rule does not cover this situation.
How then is it possible to implement a scoped_ptr? In particular, is there an alternative to writing a template specialization? This would cause large code reduplication with a realistic smart pointer implementation.
#include <cstdlib>
template<typename T>
void destroy(T* ptr)
{
delete ptr;
}
class scoped_ptr_impl_base
{
public:
virtual ~scoped_ptr_impl_base() { }
};
template<typename T, typename F>
class scoped_ptr_impl : public scoped_ptr_impl_base
{
public:
scoped_ptr_impl(T* ptr, F dtor)
: m_ptr(ptr), m_dtor(dtor)
{
}
virtual ~scoped_ptr_impl()
{
m_dtor(m_ptr);
}
private:
T* m_ptr;
F m_dtor;
};
template<typename T>
class scoped_ptr
{
public:
explicit scoped_ptr(T* ptr = 0)
: m_ptr(ptr),
m_impl(new scoped_ptr_impl<T, void (*)(T*)>(&destroy<T>))
{
}
template<typename F>
scoped_ptr(T* ptr, F dtor)
: m_ptr(ptr),
m_impl(new scoped_ptr_impl<T, F>(ptr, dtor))
{
}
~scoped_ptr()
{
delete m_impl;
}
T& operator*()
{
return *m_ptr;
}
T* operator->()
{
return m_ptr;
}
private:
T* m_ptr;
scoped_ptr_impl_base* m_impl;
scoped_ptr(const scoped_ptr&);
scoped_ptr& operator=(const scoped_ptr&);
};
int main()
{
scoped_ptr<void> p(std::malloc(1), std::free);
// scoped_ptr.cpp: In instantiation of `scoped_ptr<void>':
// scoped_ptr.cpp:76: instantiated from here
// scoped_ptr.cpp:56: error: forming reference to void
// (g++ 4.3.3)
return 0;
}
You could use a type trait for the reference type:
template<typename T>
struct type_trait
{
typedef T& reference;
};
template<>
struct type_trait<void>
{
typedef void reference;
};
then in your scoped_ptr_impl :
typename type_trait<T>::reference operator*()
{
return *m_ptr;
}
Not sure if void is the right type in the specialisation though . What type do you want it to return?