Topic: Proposal: Template specialization tweaks


Author: "Samee Zahur" <samee.zahur@gmail.com>
Date: Thu, 28 Apr 2005 22:54:48 CST
Raw View
For large template classes, specializing to get just one or two
functions added/removed currently means rewriting the entire class,
along with the function definitions. This in turn means that anyone
reading the code will have to spend a lot of time scrolling up and down
to find out the details of differences. Moreover, if I add a certain
member function later on, I must remember adding it to many other
places, or else I will get linker
errors.

So wouldn't it be nicer if we could do something like this:

class BigClass
{ /*some class without copy constructors accesible*/ };

template <class X> class myclass {
 X i;
public:
 X val() const using (X!=BigClass) {return i;}
 const X& val() const using (x==BigClass) {return i;}
 //Lots of other members
};

Admittedly, if specializations of myclass differed substantially from
the general pattern, usage of something like this would be a terrible
source of bugs hard to trace (a new function being added later might
need a different implementation for a rather obscure
set of template parameters, something the developer might overlook).
However, for large classes where differences between specializations
remain small, something like this could
reduce code size quite drastically - and *possibly* even reduce build
time, since less lines now has to be parsed.

It doesn't introduce any new keyword, but places them in a context
where it is unlikely to conflict with other usages of the keyword

I'd therefore like some opinions about pros and cons of something like
this.

Samee

P.S. although wouldn't usually be recommended, such a feature could
also include logical || or && operators to test multiple conditions at
once, > or < operators for numerical template parameters ... so on and
so forth.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "msalters" <Michiel.Salters@logicacmg.com>
Date: 30 Apr 2005 16:40:28 GMT
Raw View
Samee Zahur wrote:
> For large template classes, specializing to get just one or two
> functions added/removed currently means rewriting the entire class,
> along with the function definitions. This in turn means that anyone
> reading the code will have to spend a lot of time scrolling up and
down
> to find out the details of differences. Moreover, if I add a certain
> member function later on, I must remember adding it to many other
> places, or else I will get linker
> errors.
>
> So wouldn't it be nicer if we could do something like this:
>
> class BigClass
> { /*some class without copy constructors accesible*/ };
>
> template <class X> class myclass {
>  X i;
> public:
>  X val() const using (X!=BigClass) {return i;}
>  const X& val() const using (x==BigClass) {return i;}
>  //Lots of other members
> };

Not sure if tha't really useful, you're adding all the special
cases to the main template. Besides, I think we already can do
this using mpl and enable_if.

Anyway, the obvious alternative is to create a shorter syntax
for the specialization, i.e.

template < > class myclass<BigClass> :
  using template< typename T> myclass<T> {
    !using T myclass<T>::cal() const;
    BigClass const& val() ...
};

Basically, with this syntax you make it explicit which template
you're specializing, how the parameters are named, and which
members you don't want. Any member not undeclared is "inherited"/
not specialized.

Regards,
Michiel Salters

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gp.kiwi@gmail.com (Graeme Prentice)
Date: Sat, 30 Apr 2005 16:37:15 GMT
Raw View
On Thu, 28 Apr 2005 22:54:48 CST, Samee Zahur wrote:

>For large template classes, specializing to get just one or two
>functions added/removed currently means rewriting the entire class,
>along with the function definitions. This in turn means that anyone
>reading the code will have to spend a lot of time scrolling up and down
>to find out the details of differences. Moreover, if I add a certain
>member function later on, I must remember adding it to many other
>places, or else I will get linker
>errors.

You can "remove" member template functions for a particular
instantiation with the help of boost enable_if and you can remove
non-template member functions by specializing them for specific class
types and leaving undefined.  Similarly you can add functions with
specialization and you can selectively add data members as I wrote in my
reply to your other post.

If you don't want to modify the original class (how often does this
happen?) and you can't use a different name, then you have to duplicate
all the code as you said because there's no way that a specialization of
the class can inherit from the primary template (with the same template
arguments as its own) without using a different class name.


>
>So wouldn't it be nicer if we could do something like this:
>
>class BigClass
>{ /*some class without copy constructors accesible*/ };
>
>template <class X> class myclass {
> X i;
>public:
> X val() const using (X!=BigClass) {return i;}
> const X& val() const using (x==BigClass) {return i;}
> //Lots of other members
>};
>
>Admittedly, if specializations of myclass differed substantially from
>the general pattern, usage of something like this would be a terrible
>source of bugs hard to trace (a new function being added later might
>need a different implementation for a rather obscure
>set of template parameters, something the developer might overlook).
>However, for large classes where differences between specializations
>remain small, something like this could
>reduce code size quite drastically - and *possibly* even reduce build
>time, since less lines now has to be parsed.
>
>It doesn't introduce any new keyword, but places them in a context
>where it is unlikely to conflict with other usages of the keyword
>
>I'd therefore like some opinions about pros and cons of something like
>this.
>
>Samee
>
>P.S. although wouldn't usually be recommended, such a feature could
>also include logical || or && operators to test multiple conditions at
>once, > or < operators for numerical template parameters ... so on and
>so forth.

I don't like it because it doesn't scale well when the class has
multiple template parameters or there are multiple selecting types and
it clutters up the function declaration with detail that doesn't relate
to the job the function is doing.  It needs to scale well because even
if using || && isn't "recommended", providing the ability to write
horrendously ugly code is not a good thing.  Also "partially
specializing" doesn't work.  It also requires all the differentiating
types to be previously declared.  In any case, it requires modifying the
original class and if you can do that, there's already adequate
solutions.

So how could a class partial or explicit specialization be allowed to
make use of say, most of the primary template class without duplicating
it or modifying it?  I don't know.  It's too difficult.

Graeme

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pdimov@gmail.com (Peter Dimov)
Date: Mon, 2 May 2005 14:59:41 CST
Raw View
"Samee Zahur" <samee.zahur@gmail.com> wrote in message news:<1114668935.414725.97280@f14g2000cwb.googlegroups.com>...

[...]

> So wouldn't it be nicer if we could do something like this:
>
> class BigClass
> { /*some class without copy constructors accesible*/ };
>
> template <class X> class myclass {
>  X i;
> public:
>  X val() const using (X!=BigClass) {return i;}
>  const X& val() const using (x==BigClass) {return i;}
>  //Lots of other members
> };

I have proposed something along those lines in:

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1696.html

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Samee Zahur" <samee.zahur@gmail.com>
Date: 2 May 2005 20:10:01 GMT
Raw View
> So how could a class partial or explicit specialization be allowed to

> make use of say, most of the primary template class without
duplicating
> it or modifying it?  I don't know.  It's too difficult.

And I agree. But that was not what I am aiming to do here! What I am
trying
to do is to specialize a class (partially or explicitly) without
duplicating it BY modifying it :)

But about the way you are asking me to remove certain non-template
member functions - doesn't that require the entire class to be
redefined?
Please tell me if I'm missing something over and over again!
And the way you added functions to the template for specific cases,
I feel that will give me linker errors rather than compile-time errors
(albeit a solvable problem with yet more code).


> I don't like it because it doesn't scale well when the class has
> multiple template parameters or there are multiple selecting types
and
> it clutters up the function declaration with detail that doesn't
relate
> to the job the function is doing.

It is related to the job of the function - it says that the function
wouldn't even make sense for certain template parameters :D It serves
as a warning for anyone trying to read the code that the function makes
certain assumptions about the template parameters.

> providing the ability to write
> horrendously ugly code is not a good thing

Well, overuse of any of the language features is a misuse. Using RTTI
typeid() when a simple compile-time resolution with vanilla function
overload is sufficient, overloading operators for each and every class
just because its 'cool' ... believe me, but each and every aspect of a
language *can* yeild to misuse. That doesn't mean those features are
bad.
They are quite useful when properly used. The skills of the programmer
remains the key factor when it comes to writing good code - these
language features are just his/her aiding tools. I still maintain that
something like this is only suitable for (large or small) classes where

the differences between individual specializations are rather small.


And msalters' suggestion does enable us to "make use of most of the
primary template without duplicating or modifying it". However I feel
it gives programmers too much flexibility - it allows people to modify
behavior any class long after it was coded; plus it allows them to
write
code which is dependant on the implementational details of the class -
they can modify private data members from within these functions. Since
it becomes easier for the 'specialization patch' to be written by
someone different from the coder of the primary template, those patches
will be harder to maintain between differing versions of the primary
class' implementation. It should be a lot easier to simply group
the using declaratives together in the code of the primary template -
say
at the end of class declaration - so as to keep 'the nasty parts out of

the clean code'. This way, anyone who has to go for specialization has
to
modify the actual code of the class OR rewrite the entire class
definition
as in the current system.

Samee

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gp.kiwi@gmail.com (Graeme Prentice)
Date: Thu, 5 May 2005 21:20:47 GMT
Raw View
On 2 May 2005 20:10:01 GMT, Samee Zahur wrote:

>> So how could a class partial or explicit specialization be allowed to
>
>> make use of say, most of the primary template class without
>duplicating
>> it or modifying it?  I don't know.  It's too difficult.
>
>And I agree. But that was not what I am aiming to do here! What I am
>trying
>to do is to specialize a class (partially or explicitly) without
>duplicating it BY modifying it :)
>
>But about the way you are asking me to remove certain non-template
>member functions - doesn't that require the entire class to be
>redefined?

No.  If you're referring to the ShowType function in the Matrix class
that I wrote here  http://makeashorterlink.com/?E3D6526FA
the Matrix class is duplicated as Matrix2 because I use the Matrix2
class to show the SFINAE version  - it's two solutions in one piece of
code.  Also, it's better to use boost enable_if than what I wrote there.

>Please tell me if I'm missing something over and over again!
>And the way you added functions to the template for specific cases,
>I feel that will give me linker errors rather than compile-time errors
>(albeit a solvable problem with yet more code).

Linker errors, but only if a function is called that isn't valid for
that class specialization.  You might be able to get a compile time
error if you're lucky  e.g. you don't mind forwarding the call to
another member function.

Graeme

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Samee Zahur" <samee.zahur@gmail.com>
Date: 5 May 2005 21:30:12 GMT
Raw View
Yes, your proposal seems to be quite similar to the one here ... but
what kind of feedback did you receive?

Anyway, I have been pondering over the things Graeme has been trying to
tell me over and over again, and now I'm thinking that there really are
ways of doing things much neater than the ones in enable_if. Let me
give an example here:

template <class X,class Y> struct proceedif{static void
differ_type(){}};
template <class X> struct proceedif<X,X>{static void same_type(){}};

template <class X> class mycls
{
//....
public:
  void member_only_if_int()
  {  proceedif<X,int>::same_type();
     //proceed coding
  }
  void member_if_not_int()
  {  proceedif<X,int>::differ_type();
     //proceed coding
  }
};

After getting this in my head, I feel that something that can be done
so nicely with a two-line library is unlikely to call for a core
language change.

Thanks for the hints Graeme

Samee

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Peter Dimov" <pdimov@gmail.com>
Date: Fri, 6 May 2005 14:59:56 CST
Raw View
Samee Zahur wrote:

> Yes, your proposal seems to be quite similar to the one here ... but
> what kind of feedback did you receive?

None. The Evolution Working Group has not discussed the proposal yet,
although I've been assured that it is "on the list". ;-)

Also note that there are several "Concept" proposals on the table; some
of them offer or can approximate the same functionality. So I don't
expect much progress on conditional declarations until the fate of the
Concept proposals is decided.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]