Re: Const constructor
On 19 Jun., 04:42, Dragan Milenkovic wrote:
Anyway, here is a version of ArraySlice that you might like.
It can be implemented with SFINAE, but that gets ugly.
With "concepts" on the way, it gets a lot cleaner.
template <typename Element>
class ArraySlice {
public:
explicit ArraySlice(Element * a, int from, int to)
: m_a(a+from), m_len(to-from) {}
template <typename RhsElement>
requires Same<Element, RhsElement>
|| Same<Element, const RhsElement>
ArraySlice(ArraySlice<RhsElement> const & rhs)
: m_a(rhs.m_a), m_len(rhs.m_len) {}
template <typename RhsElement>
requires Same<Element, RhsElement>
|| Same<Element, const RhsElement>
ArraySlice & operator=(ArraySlice<RhsElement> const & rhs)
{
m_a=rhs.m_a; m_len=rhs.m_len;
return *this;
}
Element & operator[](int index) const;
private:
Element * m_a;
int m_len;
};
There are a couple of issues:
(1) SameType<Element, RhsElement> is not necessary because the
compiler
will generate a non-templated default copy-ctor
(2) SameType<Element, const RhsElement> is actually the wrong
direction.
SameType<const Element, RhsElement> is the right one.
(2) "||" for constraining templates is not part of the current draft.
(3) You forgot to declare ArraySlice<T> to be a friend of
ArraySlice<U> for T!=U.
A conceptized version of a user-defined pointer wrapper can be written
like this:
template<typename T>
class my_pointer
{
public:
template<typename> friend class my_pointer;
my_pointer(T* p) : ptr(p) {}
template<typename U> requires std::Convertible<U*,T*>
my_pointer(my_pointer<U> const& x) : ptr(x.ptr) {}
T* operator->() const {return ptr;}
T& operator*() const {return *ptr;}
private:
T* ptr;
};
A C++98 version would look like this:
#include <iostream>
/* enable_if<T,U,R>::type is R
* <==> T is const U and U is non-const
*/
template<typename T, typename U, typename R = char>
struct enable_if_cnc {};
template<typename U, typename R>
struct enable_if_cnc<const U, U, R> {typedef R type;};
template<typename T>
class my_pointer
{
public:
template<typename> friend class my_pointer;
my_pointer(T* p) : ptr(p) {}
template<typename U>
my_pointer(my_pointer<U> x,
typename enable_if_cnc<T,U>::type=0)
: ptr(x.ptr) {}
T* operator->() const {return ptr;}
T& operator*() const {return *ptr;}
private:
T* ptr;
};
int main()
{
int i = 23;
my_pointer<int> pi = &i;
my_pointer<const int> pci = pi;
*pi = 42;
std::cout << *pci << '\n';
}
The function enabler enable_if_cnc<T,U> is not exactly a translation
of Convertible<U*,T*> but it's the one I use for my 2D and 3D raster
container "locators". You can easily replace this with something like
template<typename U>
my_pointer(my_pointer<U> x,
typename enable_if< convertible<U*,T*>::value >::type=0)
: ptr(x.ptr) {}
if you want.
Cheers!
SG
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]