invalid use of 'this' outside of a non-static member function? - c++

I wrote the following code inside the public part in my Matrix<T> class:
#include <iostream>
#include "Auxiliaries.h"
namespace mtm {
template<class T>
class Matrix {
private:
Dimensions dimensions;
T *data;
public:
iterator_impl<T> begin(){};
class AccessIllegalElement;
class IllegalInitialization;
class DimensionMismatch;
Matrix(const Dimensions &matrix_dimensions, const T &initial_value = T());
};
/**Iterators**/
template<typename T>
class iterator_impl;
template<typename T>
iterator_impl<T> begin(){
return iterator(this, 0);
}
template<typename T>
class iterator_impl{
private:
const Matrix<T> *matrix;
int index;
friend class Matrix<T>;
public:
iterator_impl(const iterator_impl &) = default;
iterator_impl &operator=(const iterator_impl &) = default;
~iterator_impl() = default;
iterator_impl(const Matrix<T> *matrix, int index)
: matrix(matrix), index(index) {}
iterator_impl &operator++()
{
++index;
return *this;
}
iterator_impl operator++(int)
{
iterator_impl result = *this;
++*this;
return result;
}
bool operator==(const iterator_impl &it) const
{
return index == it.index;
}
bool operator!=(const iterator_impl &it) const
{
return !(*this == it);
}
T &operator*() const {
return matrix->data[index];
}
};
template<typename T>
using iterator = iterator_impl<T>;
template<typename T>
using const_iterator = iterator_impl<const T>;
}
But I'm getting the following error:
invalid use of 'this' outside of a non-static member function
return iterator(this, 0);
What did I do wrong here and how may I solve this one?
my class:
template<class T>
class Matrix {
private:
Dimensions dimensions;
T *data;
public:
iterator_impl<T> begin(){};
//....
}
https://wandbox.org/permlink/R4rQjGVNZWUHtMqj

What should this mean in this context?
template<typename T>
iterator_impl<T> begin(){
return iterator(this, 0);
}
It should be a pointer to the object of the class the method belongs to, but the begin function is a free function that is not a member of any class.
How do you plan to use this function? Basic patterns are:
container.begin();
or
begin(container);
In both cases there is a container: the object of the class you have forgotten in your sample.
Update
According you to your updates, this should be the pointer to the Matrix object. You have already declared the method, not let's define it. The implementation is actually up to you, I'm not sure if it is correct. The key part is that you have forgotten to specify the class in the function signature:
template<typename T>
iterator_impl<T> Matrix<T>::begin() {
return iterator(this, 0);
}

Related

Custom container list: problem with compiling from iterator to const_iterator

I am trying to recreate some of the C++ containers for a school project and for that I had to also implement iterators. I am currently working on the List container and I am facing a conversion problem.
Here are the parts of the code that are involved:
I have an Elem structure (corresponding to 1 element of a doubly linked list that I use for my List container)
template <class T>
struct Elem
{
Elem *prev;
T data;
Elem *next;
};
a BidirectionalIterator class (used for the list iterators). Here are the constructors:
template <class T>
class BidirectionalIterator
{
public:
typedef BidirectionalIterator iterator;
typedef T value_type;
typedef size_t size_type;
BidirectionalIterator() { _ptr = nullptr; };
BidirectionalIterator(Elem<value_type> *ptr) {
*this->_ptr = ptr;
};
BidirectionalIterator(const iterator &x) {
*this->_ptr = x._ptr;
};
~BidirectionalIterator() {};
iterator &operator=(const iterator &x) {
*this->_ptr = x._ptr;
return (*this);
};
[...]
};
and my list class:
template <class T, class Alloc = std::allocator<T>>
class list
{
public:
typedef T value_type;
typedef BidirectionalIterator<T> iterator;
typedef BidirectionalIterator<const T> const_iterator;
typedef size_t size_type;
/* CONSTRUCTORS */
[...]
list(const list &x) {
_init_list();
assign(x.begin(), x.end());
};
/* ITERATORS */
iterator begin() {
return (iterator(_start));
};
const_iterator begin() const {
return (const_iterator(_start));
};
iterator end() {
return (iterator(_tail));
};
const_iterator end() const {
return (const_iterator(_tail));
};
/* ASSIGN */
void assign(iterator first, iterator last);
void assign(const_iterator first, const_iterator last);
[...]
private:
Elem<value_type> *_head;
Elem<value_type> *_start;
Elem<value_type> *_end;
Elem<value_type> *_tail;
[...]
};
In my main program I' m just calling a function (T being an int) that implicitely calls the copy constructor:
void print_content(ft::list<T> lst);
But when I compile i get this:
./List.hpp:71:12: error: no matching conversion for functional-style cast from 'Elem<ft::list<int, std::allocator<int>
>::value_type> *const' (aka 'Elem<int> *const') to 'ft::list<int, std::allocator<int> >::const_iterator' (aka
'BidirectionalIterator<const int>')
return (const_iterator(_start));
^~~~~~~~~~~~~~~~~~~~~
./List.hpp:53:13: note: in instantiation of member function 'ft::list<int, std::allocator<int> >::begin' requested
here
assign(x.begin(), x.end());
./../Iterator/BidirectionalIterator.hpp:45:3: note: candidate constructor not viable: no known conversion from
'Elem<ft::list<int, std::allocator<int> >::value_type> *const' (aka 'Elem<int> *const') to
'Elem<ft::BidirectionalIterator<const int>::value_type> *' (aka 'Elem<const int> *') for 1st argument
BidirectionalIterator(Elem<value_type> *ptr) {
I don't know how to fix that problem. I already tried to delete the const attribute from my copy constructor and it works, but it needs to be const (for the rest of my project cause I'm implementing the relational operators that call a const list, and also to respect the original container constructor).
Does anyone have an idea?
You try to create an Elem<const int>* from an Elem<int> *const.
I suggest making the iterator's pointer Elem<std::remove_const_t<T>>* (even for a const_iterator) but let dereferencing a const_iterator return a T const& or T const *.
Example:
template <class T>
class BidirectionalIterator {
public:
using value_type = T;
using reference = value_type&;
using pointer = value_type*;
using size_type = std::size_t;
BidirectionalIterator() : _ptr(nullptr) {};
BidirectionalIterator(Elem<std::remove_const_t<value_type>>* ptr) : _ptr(ptr) {};
BidirectionalIterator(const BidirectionalIterator& x) {
_ptr = x._ptr;
};
BidirectionalIterator& operator=(const BidirectionalIterator& x) {
_ptr = x._ptr;
return *this;
};
reference operator*() const { return _ptr->data; }
pointer operator->() const { return &_ptr->data; }
Elem<std::remove_const_t<value_type>>* _ptr;
};
A slightly better version to let you create lists of const Ts and to also let you convert iterators to const_iterators (but not the other way around) to be able to compare iterators could look like this:
#include <memory>
#include <type_traits>
template <class T, class ElemType> // const or non-const T and the type used in Elem
class BidirectionalIterator {
public:
using value_type = T;
using reference = value_type&;
using pointer = value_type*;
using size_type = std::size_t;
BidirectionalIterator() : _ptr(nullptr) {};
BidirectionalIterator(Elem<ElemType>* ptr) : _ptr(ptr) {};
// let a conversion constructor of the const_iterator read _ptr
friend class BidirectionalIterator<const ElemType, ElemType>;
// enable a const_iterator to be created from a non-const iterator via
// a conversion constructor
template<typename U = T, typename V = ElemType,
std::enable_if_t<std::is_const_v<U>&&!std::is_const_v<V>, int> = 0
>
BidirectionalIterator(const BidirectionalIterator<ElemType, ElemType>& x) :
_ptr(x._ptr) {}
// normal copy ctor
BidirectionalIterator(const BidirectionalIterator& x) : _ptr(x._ptr) {}
BidirectionalIterator& operator=(const BidirectionalIterator& x) {
_ptr = x._ptr;
return *this;
};
// the conversion constructor lets you compare a const_iterator and an iterator
bool operator==(const BidirectionalIterator& rhs) const {
return _ptr == rhs._ptr;
}
bool operator!=(const BidirectionalIterator& rhs) const {
return !(_ptr == rhs._ptr);
}
reference operator*() const { return _ptr->data; }
pointer operator->() const { return &_ptr->data; }
private:
Elem<ElemType>* _ptr;
};
// iterator == const_iterator, swap order to use member operator==
template<typename T>
bool operator==(const BidirectionalIterator<T, T>& a,
const BidirectionalIterator<const T, T>& b) {
return b == a;
}
// iterator != const_iterator, swap order to use member operator!=
template<typename T>
bool operator!=(const BidirectionalIterator<T, T>& a,
const BidirectionalIterator<const T, T>& b) {
return b != a;
}
With this iterator definition, you'd need to define your iterator and const_iterator slightly different.
template <class T, class Alloc = std::allocator<T>>
class list {
public:
using value_type = T;
using iterator = BidirectionalIterator<T, T>;
using const_iterator = BidirectionalIterator<const T, T>;
//...

Iterators and Const iterators in C++?

Let's suppose I have two classes, the first:
class IntMatrix::iterator {
private:
const IntMatrix *int_matrix;
int index;
iterator(const IntMatrix *int_matrix, int index);
friend class IntMatrix;
public:
int &operator*() const;
iterator &operator++();
iterator operator++(int);
bool operator==(const iterator &it) const;
bool operator!=(const iterator &it) const;
iterator(const iterator &) = default;
iterator &operator=(const iterator &) = default;
~iterator() = default;
};
and the second is:
class IntMatrix::const_iterator {
private:
const IntMatrix *int_matrix;
int index;
const_iterator(const IntMatrix *int_matrix, int index);
friend class IntMatrix;
public:
const int &operator*() const;
const_iterator &operator++();
const_iterator operator++(int);
bool operator==(const const_iterator &it) const;
bool operator!=(const const_iterator &it) const;
const_iterator(const const_iterator &) = default;
const_iterator &operator=(const const_iterator &) = default;
~const_iterator() = default;
};
How may I prevent code duplication here, since the implementation is 99% the same?
How about generics may it help here or inheritance?
An example of how they are implemented:
int &IntMatrix::iterator::operator*() const {
return int_matrix->data[index];
}
const int &IntMatrix::const_iterator::operator*() const {
return int_matrix->data[index];
}
Plus, I want In main to allow something like:
IntMatrix::iterator it;
Update:
I'm trying to implement the given solution on a Generic class called Matrix in the following way: (Note the code shown is all written as public in my class)
template<typename T>
class iterator_impl;
template<typename T>
iterator_impl<T> begin(){
return iterator(this, 0);
}
template<typename T>
iterator_impl<T> end(){
return iterator(this, size());
}
template<typename T>
iterator_impl<const T> begin() const
{
return const_iterator(this, 0);
}
template<typename T>
iterator_impl<const T> end() const
{
return const_iterator(this, size());
}
template<typename T>
class iterator_impl{
private:
const Matrix<T> *matrix;
int index;
friend class Matrix<T>;
public:
iterator_impl(const iterator_impl &) = default;
iterator_impl &operator=(const iterator_impl &) = default;
~iterator_impl() = default;
iterator_impl(const Matrix<T> *int_matrix, int index)
: matrix(int_matrix), index(index) {}
iterator_impl &operator++()
{
++index;
return *this;
}
iterator_impl operator++(int)
{
iterator_impl result = *this;
++*this;
return result;
}
bool operator==(const iterator_impl &it) const
{
return index == it.index;
}
bool operator!=(const iterator_impl &it) const
{
return !(*this == it);
}
T &operator*() const {
if (index < 0 || index > matrix->size() - 1) {
throw Matrix<T>::AccessIllegalElement();
}
return matrix->data[index];
}
};
template<typename T>
using iterator = iterator_impl<T>;
template<typename T>
using const_iterator = iterator_impl<const T>;
and I'm getting some errors like:
invalid use of 'this' outside of a non-static member function
return iterator(this, 0);
One way is to make the implementation into a class template and then to make aliases for the const and non-const instantiations.
Plus, I want In main to allow something like:
IntMatrix::iterator it;
You then need to add a default constructor.
Example:
#include <cstddef>
#include <type_traits>
// in the .hpp file:
class IntMatrix {
private:
int data[10]; // just an example
size_t size = 10; // just an example
template<typename T>
class iterator_impl;
public:
// two typedefs using the template:
using iterator = iterator_impl<int>;
using const_iterator = iterator_impl<const int>;
const_iterator cbegin() const;
const_iterator cend() const;
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
};
// still in the .hpp file:
template<typename T>
class IntMatrix::iterator_impl {
public:
using matrix_type =
std::conditional_t<
std::is_const_v<T>,
const IntMatrix,
IntMatrix
>;
private:
matrix_type* int_matrix;
size_t index;
friend IntMatrix;
iterator_impl(matrix_type* im, size_t idx) :
int_matrix(im), index(idx)
{}
public:
iterator_impl() = default; // default constructor
//iterator_impl(const iterator_impl&) = default; // not needed
//iterator_impl &operator=(const iterator_impl &) = default; // not needed
//~iterator_impl() = default; // not needed
iterator_impl &operator++() {
++index;
return *this;
}
iterator_impl operator++(int) {
iterator_impl old(*this);
++index;
return old;
}
bool operator!=(const iterator_impl &it) const {
return index != it.index || int_matrix != it.int_matrix;
}
bool operator==(const iterator_impl &it) const {
return !(*this != it);
}
T& operator*() const {
return int_matrix->data[index];
}
};
// in the .cpp file:
IntMatrix::const_iterator IntMatrix::cbegin() const { return {this, 0}; }
IntMatrix::const_iterator IntMatrix::cend() const { return {this, size}; }
IntMatrix::const_iterator IntMatrix::begin() const { return cbegin(); }
IntMatrix::const_iterator IntMatrix::end() const { return cend(); }
IntMatrix::iterator IntMatrix::begin() { return {this, 0}; }
IntMatrix::iterator IntMatrix::end() { return {this, size}; }
Demo
Edit: If Matrix is a class template itself, you need to change the iterator slightly.
#include <cstddef>
#include <type_traits>
// in the .hpp file:
template<typename T>
class Matrix {
private:
T data[10]; // just an example
size_t size = 10; // just an example
template<typename I>
class iterator_impl;
public:
// two typedefs using the template:
using iterator = iterator_impl<T>;
using const_iterator = iterator_impl<const T>;
auto cbegin() const;
auto cend() const;
auto begin() const;
auto end() const;
auto begin();
auto end();
};
// still in the .hpp file:
template<typename T>
template<typename I>
class Matrix<T>::iterator_impl {
public:
using value_type = std::remove_const_t<I>;
using matrix_type =
std::conditional_t<
std::is_const_v<I>,
const Matrix<value_type>,
Matrix<value_type>
>;
private:
matrix_type* matrix;
size_t index;
friend Matrix;
iterator_impl(matrix_type* im, size_t idx) :
matrix(im), index(idx)
{}
public:
iterator_impl() = default; // default constructor
iterator_impl& operator++() {
++index;
return *this;
}
iterator_impl operator++(int) {
iterator_impl old(*this);
++index;
return old;
}
bool operator!=(const iterator_impl &it) const {
return index != it.index || matrix != it.matrix;
}
bool operator==(const iterator_impl &it) const {
return !(*this != it);
}
I& operator*() const {
return matrix->data[index];
}
};
// still in the .hpp file
template<typename T> auto Matrix<T>::cbegin() const { return const_iterator{this, 0}; }
template<typename T> auto Matrix<T>::cend() const { return const_iterator{this, size}; }
template<typename T> auto Matrix<T>::begin() const { return cbegin(); }
template<typename T> auto Matrix<T>::end() const { return cend(); }
template<typename T> auto Matrix<T>::begin() { return iterator{this, 0}; }
template<typename T> auto Matrix<T>::end() { return iterator{this, size}; }
Demo

Interface which declares functions for iteration

I have an assignment in which I need to make template classes LinkedList and Traversible. Class Traversible needs to be a interface which declares functions for indexing and iteration of some collection class. I don't exactly know how to make an interface for iterator so LinkedList can use it. I was thinking something like
template <class T, class U>
class ITraversible {
public:
virtual U begin() noexcept = 0;
virtual U end() noexcept = 0;
virtual T& operator[](int) = 0;
};
and then in LinkedList header file I would do:
template <class T>
class LinkedList : public ITraversible<T,typename LinkedList<T>::iterator> {
struct node {
T data;
node* next, *prev;
explicit node(const T&);
void connect(node*);
};
node *head, *tail;
int n;
public:
/*************************ITERATOR************************/
class iterator : public std::iterator<std::bidirectional_iterator_tag, node*> {
typename LinkedList<T>::node* itr;
explicit iterator(node*) noexcept;
friend class LinkedList;
public:
iterator& operator++();
iterator operator++(int);
iterator& operator--();
iterator operator--(int);
bool operator==(const iterator&) const noexcept;
bool operator!=(const iterator&) const noexcept;
T& operator*() const noexcept;
T& operator->() const noexcept;
};
/**********************************************************/
LinkedList() noexcept;
LinkedList(std::initializer_list<T>);
LinkedList(const LinkedList&);
LinkedList(LinkedList&&) noexcept;
~LinkedList() noexcept;
LinkedList& operator=(LinkedList) noexcept;
template <class A>
friend void swap(LinkedList<A>&, LinkedList<A>&);
void add(const T&);
void removeAt(int);
int size() const noexcept;
bool operator==(const LinkedList&) const noexcept;
bool operator!=(const LinkedList&) const noexcept;
virtual T& operator[](int) override;
virtual iterator begin() noexcept override;
virtual iterator end() noexcept override;
};
But then Traversable template has two parameters and it should have only one.
Is this what I am supposed to do? Keep in mind I am new to templates and iterators.
When creating an interface you'll need to nail down the static types of what is being returned. These may behave dynamically different but you can't change the type other than using a subtype relation when returning pointers or references.
Personally, I think this exercise is ill-advised for a C++ context. It may make some sense when using Java or C#. However, similar behavior can be obtained. A rought sketch would be something like this (although this should work it will be rather slow):
template <typename T>
struct iterator_base {
virtual iterator_base() {}
virtual iterator_base<T>* do_clone() = 0;
virtual T& do_value() = 0;
virtual void do_next() = 0;
virtual bool do_equal() = 0;
// other operations to implement operator--, operator[], ...
};
template <typename It>
class iterator: iterator_base<typename std::iterator_traits<It>::value_type> {
typedef typename std::iterator_traits<It>::value_type> type;
It it;
iterator_base<type>* do_clone() { return new iterator<It>(*this); }
type& do_value() { return *this->it; }
void do_next() { ++this->it; }
bool do_equal(iterator_base<type>* other) {
return this->it == static_cast<iterator<It>>(other)->it;
}
};
template <typename T>
class poly_iterator {
std::unique_ptr<iterator_base<T>> ptr;
public:
poly_iterator(iterator_base<T>* ptr): ptr(ptr) {}
poly_iterator(poly_iterator const& other): ptr(other.ptr->clone()) {}
poly_iterator& operator= (poly_iterator other) {
other.swap(this);
return *this;
}
void swap(poly_iterator& other) { swap(this->ptr, other.ptr); }
T& operator*() { return this->ptr->value(); }
T* operator->() { return &this->operator*(); }
poly_iterator& operator++() { this->ptr->next(); return *this; }
poly_iterator operator++(int) {
poly_iterator rc(*this);
this->operator++();
return rc;
}
bool operator== (poly_iterator const& other) {
return this->ptr->equal(other.ptr.ptr());
}
bool operator!= (poly_iterator const& other) {
return !(*this == other);
}
// other operations
};
// define a suitable specialization of std::iterator_traits<poly_iterator<T>>
template <typename T>
class ITraversible {
virtual iterator_base<T>* do_begin() = 0;
virutal iterator_base<T>* do_end() = 0;
public:
poly_iterator<T> begin() { return this->do_begin(); }
poly_iterator<T> end() { return this->do_end(); }
// other operations
};
template <typename T>
class List: public ITraversible<T> {
std::list<T> list;
iterator_base<T>* do_begin() {
return iterator<std::list<T>::iterator>(list.begin());
}
iterator_base<T>* do_end() {
return iterator<std::list<T>::iterator>(list.end());
}
public:
// whatever is needed to fill the list
};

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;

clone_ptr implementation error

I have the following implementation of a clone_ptr in an attempt to make safe copies of object pointers that need to be copied in a class, so instead of using the copy constructor, I was adviced to use smart pointers and create a clone pointer.
Clone_ptr implementation:
#include <algorithm>
#include <functional>
#include <xercesc/dom/DOM.hpp>
struct DOMImplementation_cloner
{
template <typename T>
T* operator()(T* pPtr) const
{
/* your clone code*/.
T = DOMImplementationRegistry::getDOMImplementation(X("Core"));
}
};
struct default_clone
{
template <typename T>
T* operator()(T* pPtr) const
{
return pPtr->clone();
}
};
template <typename T, typename Cloner = default_clone>
class clone_ptr
{
public:
// types
typedef T element_type;
typedef element_type value_type;
typedef const element_type const_value_type;
typedef value_type* pointer;
typedef const_value_type* const_pointer;
typedef value_type& reference;
typedef const_value_type& const_reference;
// creation
clone_ptr() :
mPtr(0)
{}
explicit clone_ptr(pointer pPtr) :
mPtr(pPtr)
{}
clone_ptr(const clone_ptr& pOther) :
mPtr(pOther.get() ? mCloner(pOther.get()) : 0)
{}
/* clone_ptr(const clone_ptr& pOther) :
mPtr(pOther.get() ? pOther->clone() : 0),
{}*/
clone_ptr& operator=(clone_ptr pOther)
{
swap(*this, pOther);
return *this;
}
~clone_ptr()
{
delete get();
}
// observers
pointer get() const
{
return mPtr;
}
pointer operator->() const
{
return get();
}
reference operator*() const
{
assert(get() != 0);
return *get();
}
// modifiers
pointer release()
{
pointer result = mPtr;
mPtr = 0;
return result;
}
void reset(pointer pPtr = 0)
{
*this = clone_ptr(pPtr);
}
// utility
friend void swap(clone_ptr& pFirst, clone_ptr& pSecond)
{
std::swap(pFirst.mPtr, pSecond.mPtr);
}
/////////////////////
// compare
template <typename T1, typename T2>
friend bool operator==(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return pFirst.get() == pSecond.get();
}
template <typename T1, typename T2>
friend bool operator!=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst == pSecond);
}
template <typename T1, typename T2>
friend bool operator<(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return std::less<void*>()(pFirst.get(), pSecond.get());
}
template <typename T1, typename T2>
friend bool operator<=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst > pSecond);
}
template <typename T1, typename T2>
friend bool operator>(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return pSecond < pFirst;
}
template <typename T1, typename T2>
friend bool operator>=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst < pSecond);
}
template <typename T1>
friend bool operator!(const clone_ptr<T1>& pX)
{
return pX.get() == 0;
}
private:
pointer mPtr;
default_clone mCloner;
};
/// Use of a xerces pointer so it can be copied/cloned safely
private class member:
clone_ptr<DOMImplementation, DOMImplementation_cloner> impl;
//compiler error:
error C2039: 'clone' : is not a member of 'xercesc_3_1::DOMImplementation'
I don't understand why it is not using the DOMImplementation_cloner and tries to use the default_clone instead?
Can someone clarify as to what I'm doing wrong?
The type of the cloner is hard-coded to default_clone, instead of using the template parameter Cloner (see the last line of your class definition).
Edit Just to make sure you understand, your definition of mCloner should look like this:
Cloner mCloner;
This way the cloner will actually be of the type given by the template parameter.
One more thing. If you expect you clone_ptr to be used in a more general setting (e.g. by coworkers on other projects), you should make the type of the cloner a property of the type T. This can be done using type traits (this answer gives an example). This could look like this in your clone_ptr:
template< typename T, typename Cloner = cloner_traits< T >::cloner_type >
class clone_ptr {
// ...
};
This would have the same default behavior as your current implementation. The advantage is that classes that require a special cloner would just specialize the cloner_traits template and the user of the class does not have to worry about choosing the appropriate cloner. If you still want to override the cloner for any class, you can still pass the cloner manually.
I recommend using clone_ptr class in following link:
http://www.codeproject.com/KB/stl/clone_ptr.aspx
The above type of clone pointer does not need to have a clone function.
There are other advantages to this type of clone pointer class, over above type implementation.
See article for more details.