It seems the solution with deriving classes works!
Here's my code:
template <typename T>class array;template<typename T>class array<const T> {public: array(); array(size_t size, const T *v); array(const array<const T>& rhs);protected: array(size_t size, const T *v, uint *num_refs);public: static array<const T> cast(const T *v, size_t size); ~array(); array<const T>& operator=(const array<const T>& rhs); const T& operator[](int idx) const; size_t get_byte_size() const; array<T> copy() const; const T *raw() const;public: const size_t size;protected: const T *data; uint *num_refs;};template<typename T>class array : public array<const T> {public: array(); explicit array(size_t size); array(size_t size, const T *v); array(const array<T>& rhs);private: array(size_t size, T *v, uint *num_refs);public: static array<T> cast(T *v, size_t size); T& operator[](int idx) const; T *raw() const;};template <typename T>inline array<T>::array() : array<const T>() { };template <typename T>inline array<T>::array(size_t size) : array<const T>(size, new T[size], new uint(1)) { };template <typename T>inline array<T>::array(size_t size, const T *v) : array<const T>(size, v) { };template <typename T>inline array<T>::array(const array<T>& rhs) : array<const T>(rhs) { };template <typename T>inline array<T>::array(size_t size, T *v, uint *num_refs) : array<const T>(size, v, num_refs) { };template <typename T>inline static array<T> array<T>::cast(T *v, size_t size){ return array<T>(size, v, NULL);};template <typename T>inline T& array<T>::operator[](int idx) const{ conditional::throw_if_array_out_of_bounds<options::throw_array_out_of_bounds>::perform(*this, idx); return const_cast<T& >(data[idx]);};template <typename T>inline T *array<T>::raw() const{ return const_cast<T *>(data);};template <typename T>inline array<const T>::array() : data(NULL), size(0), num_refs(NULL) { };template <typename T>inline array<const T>::array(size_t size, const T *v) : size(size), data(new T[size]), num_refs(new uint(1)){ copy(data, v, size);};template <typename T>inline array<const T>::array(const array<const T>& rhs) : data(rhs.data), size(rhs.size), num_refs(rhs.num_refs){ if (num_refs) ++*num_refs;};template <typename T>inline array<const T>::array(size_t size, const T *v, uint *num_refs) : data(v), size(size), num_refs(num_refs) { };template <typename T>inline array<const T> array<const T>::cast(const T *v, size_t size){ return array<const T>(size, v, NULL);};template <typename T>inline array<const T>::~array(){ if (num_refs && !--*num_refs) { delete[] data; delete num_refs; }};template <typename T>inline array<const T>& array<const T>::operator=(const array<const T>& rhs){ if (rhs.num_refs) ++*rhs.num_refs; if (num_refs && !--*num_refs) { delete[] data; delete num_refs; } data = rhs.data; const_cast<uint& >(size) = rhs.size; num_refs = rhs.num_refs; return *this;};template <typename T>inline const T& array<const T>::operator[](int idx) const{ conditional::throw_if_array_out_of_bounds<options::throw_array_out_of_bounds>::perform(*this, idx); return data[idx];};template <typename T>inline uint array<const T>::get_byte_size() const{ return size * sizeof(T);};template <typename T>inline array<T> array<const T>::copy() const{ array<T> b(size); copy(b.data, data, size); return b;};template <typename T>inline const T *array<const T>::raw() const{ return data;};
array<int> a1;array<const int> a2;a1 = a2; // wrong, doesn't compilea2 = a1; // okvoid f1(array<int>& );void f2(array<const int>& );f1(a1); // okf1(a2); // wrong, doesn't compilef2(a1); // okf2(a2); // ok
No temporary objects are created.
What do you think about it?
[Edited by - rozz666 on October 13, 2007 2:09:13 PM]