From: Nikolay Ivchenkov on
Sometimes we need to duplicate code for cv-unqualified and cv-
qualified types. For example, there is no way to specialize the
following template

template <class T>
struct X;

for any pointer type at once. We have to write 4 partial
specializations as shown below:

template <class T>
struct X<T *> { /* ... */ };
template <class T>
struct X<T *const> { /* ... */ };
template <class T>
struct X<T *volatile> { /* ... */ };
template <class T>
struct X<T *const volatile> { /* ... */ };

With additional kind of template parameters a single common partial
specialization for pointer types might look like this:

template <class T, const volatile cvq>
struct X<T *cvq>
{
//...
};

where cvq designates empty cv-qualification, const, volatile, or const
volatile. Similarly, a single common partial specialization (instead
of 16 partial specializations) for pointer to member function types
might look like this:

template
<
class R,
class C,
class... Params,
const volatile ptr_cvq,
const volatile fun_cvq
>
struct X<R (C::*ptr_cvq)(Params...) fun_cvq>
{
//...
};

We might also implement non-const and const member functions in a
single template:

template <class T>
class Vector
{
template <const cq = void>
using iterator_type = T cq *;
// here 'void' designates empty cv-qualification

typedef iterator_type<> iterator;
typedef iterator_type<const> const_iterator;

template <const cq>
iterator_type<cq> begin() cq;

const_iterator cbegin() const
{
return begin<const>();
}

template <const cq>
T cq &front() cq;

// ...
};

// ...

void f(Vector<int> const &c)
{
int i = c.begin();
// cq is deduced to const

c.begin<const volatile>();
// ill-formed: template argument for cq
// shall not contain volatile qualifier
}

Did the committee consider this language improvement?

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Dragan Milenkovic on
Nikolay Ivchenkov wrote:
> Sometimes we need to duplicate code for cv-unqualified and cv-
> qualified types. For example, there is no way to specialize the
> following template
> template <class T>
> struct X;
> for any pointer type at once. We have to write 4 partial
> specializations as shown below:
> template <class T>
> struct X<T *> { /* ... */ };
> template <class T>
> struct X<T *const> { /* ... */ };
> template <class T>
> struct X<T *volatile> { /* ... */ };
> template <class T>
> struct X<T *const volatile> { /* ... */ };

Maybe you have already considered, but you can do it like this:

template <class T>
struct X<T * const> : public Y<T *, CQ_CONST> {};

or

template <class T>
struct X<T * const> : public Y<T *, true, false> {};

Of course, you put your implementation in Y which would be common
for all qualifications.

--
Dragan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: terminator on
On Jul 5, 12:52 am, Dragan Milenkovic <dra...(a)plusplus.rs> wrote:
> Nikolay Ivchenkov wrote:
> > Sometimes we need to duplicate code for cv-unqualified and cv-
> > qualified types. For example, there is no way to specialize the
> > following template
> > template <class T>
> > struct X;
> > for any pointer type at once. We have to write 4 partial
> > specializations as shown below:
> > template <class T>
> > struct X<T *> { /* ... */ };
> > template <class T>
> > struct X<T *const> { /* ... */ };
> > template <class T>
> > struct X<T *volatile> { /* ... */ };
> > template <class T>
> > struct X<T *const volatile> { /* ... */ };
>
> Maybe you have already considered, but you can do it like this:
>
> template <class T>
> struct X<T * const> : public Y<T *, CQ_CONST> {};
>
> or
>
> template <class T>
> struct X<T * const> : public Y<T *, true, false> {};
>
> Of course, you put your implementation in Y which would be common
> for all qualifications.
>

and that would again require multiple(4,16,...) definition lines for
x.

regards,
FM.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Johannes Schaub (litb) on
Dragan Milenkovic wrote:

> Nikolay Ivchenkov wrote:
>> Sometimes we need to duplicate code for cv-unqualified and cv-
>> qualified types. For example, there is no way to specialize the
>> following template
>> template <class T>
>> struct X;
>> for any pointer type at once. We have to write 4 partial
>> specializations as shown below:
>> template <class T>
>> struct X<T *> { /* ... */ };
>> template <class T>
>> struct X<T *const> { /* ... */ };
>> template <class T>
>> struct X<T *volatile> { /* ... */ };
>> template <class T>
>> struct X<T *const volatile> { /* ... */ };
>
> Maybe you have already considered, but you can do it like this:
>
> template <class T>
> struct X<T * const> : public Y<T *, CQ_CONST> {};
>
> or
>
> template <class T>
> struct X<T * const> : public Y<T *, true, false> {};
>
> Of course, you put your implementation in Y which would be common
> for all qualifications.
>

I think implementing that template in particular was just an example for
making his point. In fact for implementing this one, there is an easy
solution for specializing all pointer types at once:

template<typename T> struct Ximpl;
template<typename T>
struct Ximpl<T *const volatile> { /* ... */ };

template<typename T>
struct X : Ximpl<T const volatile> { };

Of course this way you lost the original type, but you can easily pass it
along unmodified to "Ximpl".

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Dragan Milenkovic on
On 07/10/2010 04:12 PM, terminator wrote:
> On Jul 5, 12:52 am, Dragan Milenkovic<dra...(a)plusplus.rs> wrote:
>> Nikolay Ivchenkov wrote:
>>> Sometimes we need to duplicate code for cv-unqualified and cv-
>>> qualified types. For example, there is no way to specialize the
>>> following template
>>> template<class T>
>>> struct X;
>>> for any pointer type at once. We have to write 4 partial
>>> specializations as shown below:
>>> template<class T>
>>> struct X<T *> { /* ... */ };
>>> template<class T>
>>> struct X<T *const> { /* ... */ };
>>> template<class T>
>>> struct X<T *volatile> { /* ... */ };
>>> template<class T>
>>> struct X<T *const volatile> { /* ... */ };
>>
>> Maybe you have already considered, but you can do it like this:
>>
>> template<class T>
>> struct X<T * const> : public Y<T *, CQ_CONST> {};
>>
>> or
>>
>> template<class T>
>> struct X<T * const> : public Y<T *, true, false> {};
>>
>> Of course, you put your implementation in Y which would be common
>> for all qualifications.
>>
>
> and that would again require multiple(4,16,...) definition lines for
> x.

It is still better to have one-liners with no body than 4 copy/pasted
implementations, don't you agree?

--
Dragan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]