Topic: Overloading functions by value? Possible?


Author: mhamilton@bunge.com.au (Mab)
Date: 1997/03/04
Raw View
I had a thought the other day (hurt a lot!), and decided to post to see
whether my idea was possible.

>From what I know of c++, it is possible to create a template class which acts
on a value, rather than a type, like this:

template< int i >
class Array
{
   /* declaration array with i elements */
};

and I have a feeling (although I'm not sure) that it's also possible to supply
a default, like this:

template< int i = 10 >
class Array
{
   /* array with i elements, or 10 if none specified */
};

Also, again if memory serves me correct, it is possible to specialise 'type
templates' like this:

template< class T >
class ATemplate { /* blah blah blah */ };

template< char >
class ATemplate { /* blah blah blah */ };

So, then, is it possible to specialise a value? Like if I wanted a special
case when my user creates an array of 5 elements:

template< 5 >
class Array { /* declaration of special-case 5 element array */ };

????

If it's not possible, then why not? I figure you could then use template
functions and have special case functions, like this:

template< int i >
int square< i >()
{
   return i * i;
}

int square< 1 >()
{
   return 1;
}


If you get my drift. This is a pretty poultry example, I conceed.

Any takers?

|~\  /~| /~~| |~|    _______________________________________________
|  \/  |/ / |_| |__  The .sig wears a ring of polymorph! --More--
|      ' /| |_| | /  The .login hits! The .cshrc bites!
| |\/|  /\  | |  /   -----------------------------------------------
| |  |_/  \_| | /    "Say . . . That's a nice bike!" -- The T1000
=\|===========|/==========- The Mabster:  mhamilton@bunge.com.au -==
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/03/05
Raw View
mhamilton@bunge.com.au (Mab) writes:

> If it's not possible, then why not? I figure you could then use template
> functions and have special case functions, like this:
>
> template< int i >
> int square< i >()
> {
>    return i * i;
> }
>
> int square< 1 >()
> {
>    return 1;
> }

Actually this is possible and has been suggested semi-seriously by
some authors.  I have heard of a template based solution that actually
calculates Fibonacci numbers.  A heavily optimised implementation
reduces the template function to a single constant -- the answer.

These things are usually contrived and serve better as intellectual
exercises than practical solutions.  The above example should simply
have been:

  inline int square(int i) { return i * i; }

Most compilers will reduce this to a constant when supplied a constant
argument.


--
______________________________________________________________________
Marcelo Cantos, Research Assistant             marcelo@mds.rmit.edu.au
Multimedia Database Systems Group, RMIT__/_      _  Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053    Aus/ralia ><_> Fax 61-3-9282-2490
                                       /
Acknowledgements: errors - me; wisdom - God; funding - RMIT
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "B. K. Oxley (binkley)" <boxley%dev.cm.ssb.com@clipper.ssb.com>
Date: 1997/03/05
Raw View
[Moderator's summary: yes, it is possible.
This post gives some examples of where it might be useful.
P.S.  Posters, please remember to trim quotes.  -fjh.]

Mab wrote:

  I had a thought the other day (hurt a lot!), and decided to post to
  see whether my idea was possible.

  From what I know of c++, it is possible to create a template class
  which acts on a value, rather than a type, like this:

  template< int i >
  class Array
  {
     /* declaration array with i elements */
  };

  and I have a feeling (although I'm not sure) that it's also possible
  to supply a default, like this:

  template< int i = 10 >
  class Array
  {
     /* array with i elements, or 10 if none specified */
  };

  Also, again if memory serves me correct, it is possible to
  specialise 'type templates' like this:

  template< class T >
  class ATemplate { /* blah blah blah */ };

  template< char >
  class ATemplate { /* blah blah blah */ };

  So, then, is it possible to specialise a value? Like if I wanted a
  special case when my user creates an array of 5 elements:

  template< 5 >
  class Array { /* declaration of special-case 5 element array */ };

  ????

  If it's not possible, then why not? I figure you could then use
  template functions and have special case functions, like this:

  template< int i >
  int square< i >()
  {
     return i * i;
  }

  int square< 1 >()
  {
     return 1;
  }

  If you get my drift. This is a pretty poultry example, I conceed.

  Any takers?

For a pretty keen example of this, see Todd Veldhuizen's paper on
"Template Metaprograms" at
http://monet.uwaterloo.ca/~tveldhui/papers/Template-Metaprograms/meta-art.html

A quick example is the factorial function:

template<int N>
struct Factorial
{
  enum {value = N * Factorial<N-1>::value};
};

struct Factorial<0>
{
  enum {value = 1};
}

Then, you can have a compile-time evaluation of 6!, thus:
#define FACTORIAL(N) (Factorial<N>::value)

int
main ( )
{
  return FACTORIAL (6);
}

--binkley
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Date: 1997/03/05
Raw View
mhamilton@bunge.com.au (Mab) writes:

|>  I had a thought the other day (hurt a lot!), and decided to post to see
|>  whether my idea was possible.
|>
|>  >From what I know of c++, it is possible to create a template class which acts
|>  on a value, rather than a type, like this:
|>
|>  template< int i >
|>  class Array
|>  {
|>     /* declaration array with i elements */
|>  };

Of course.  This has always been the case.

|>  and I have a feeling (although I'm not sure) that it's also possible to supply
|>  a default, like this:
|>
|>  template< int i = 10 >
|>  class Array
|>  {
|>     /* array with i elements, or 10 if none specified */
|>  };

I'm not sure, but I would imagine so.  (None of my compilers support
default template arguments, so I've not really studied the problem in
detail.)

|>  Also, again if memory serves me correct, it is possible to specialise 'type
|>  templates' like this:
|>
|>  template< class T >
|>  class ATemplate { /* blah blah blah */ };
|>
|>  template< char >
|>  class ATemplate { /* blah blah blah */ };

The exact method of doing this varies from one compiler to the other,
but it certainly possible.

|>  So, then, is it possible to specialise a value?

But of course.  This is even necessary in the case of recursive
templates; the classical example is a compile time factorial:

    template< int n >
    struct fact { enum { value = n * fact< n - 1 >::value } ; } ;

    template< 0 >
    struct fact { enum { value = 1 } ; } ;

|>  Like if I wanted a special
|>  case when my user creates an array of 5 elements:
|>
|>  template< 5 >
|>  class Array { /* declaration of special-case 5 element array */ };

No problem.

|>  If it's not possible, then why not? I figure you could then use template
|>  functions and have special case functions, like this:
|>
|>  template< int i >
|>  int square< i >()
|>  {
|>     return i * i;
|>  }
|>
|>  int square< 1 >()
|>  {
|>     return 1;
|>  }
|>
|>
|>  If you get my drift. This is a pretty poultry example, I conceed.
|>
|>  Any takers?

It's been done.  I first saw the factorial example, above, a long time
ago.  (I think that at the time, it was mainly meant to be a compiler
stress test.)

--
James Kanze      home:     kanze@gabi-soft.fr        +33 (0)1 39 55 85 62
                 office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 22 rue Jacques-Lemercier, F-78000 Versailles France
     -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/03/05
Raw View
Mab wrote:
>From what I know of c++, it is possible to create a template class which acts
> on a value, rather than a type, like this:
>
> template< int i >
> class Array
> {
>    /* declaration array with i elements */
> };
>
> and I have a feeling (although I'm not sure) that it's also possible to supply
> a default, like this:
>
> template< int i = 10 >
> class Array
> {
>    /* array with i elements, or 10 if none specified */
> };

Right

> Also, again if memory serves me correct, it is possible to specialise 'type
> templates' like this:
>
> template< class T >
> class ATemplate { /* blah blah blah */ };
>
> template< char >
> class ATemplate { /* blah blah blah */ };

You mean:

template <>
class ATemplate<char> { /* blah blah blah */ };

> So, then, is it possible to specialise a value? Like if I wanted a special
> case when my user creates an array of 5 elements:

Dec 95 DWP says:

  14.1  Template parameters                                 [temp.param]

8 A default template-argument is a type, value,  or  template  specified
  after  =  in a template-parameter.  A default template-argument may be
  specified for both a type and non-type template-parameter.  A  default
  template-argument  may be specified in a class template declaration or
  a class template definition.  A default template-argument shall not be
  specified  in  a  function template declaration or a function template
  definition.  The set of default template-arguments available  for  use
  with  a  template in a translation unit shall be provided by the first
  declaration of the template in that translation unit.

> If it's not possible, then why not? I figure you could then use template
> functions and have special case functions, like this:
>
> template< int i >
> int square< i >()
> {
>    return i * i;
> }
>
> int square< 1 >()
> {
>    return 1;
> }

IMO because it could interfere with function arg deduction.

Your example isn't a very good one but a recursive function
vould be a better idea (since you have to stop somewhere).

--

Valentin Bonnard
mailto:bonnardv@pratique.fr
http://www.pratique.fr/~bonnardv (Informations sur le C++ en Francais)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/03/06
Raw View
Valentin Bonnard <bonnardv@pratique.fr> writes:

>Mab wrote:
>> If it's not possible, then why not? I figure you could then use template
>> functions and have special case functions, like this:
>>
>> template< int i >
>> int square< i >()
>> {
>>    return i * i;
>> }
>>
>> int square< 1 >()
>> {
>>    return 1;
>> }

Yes, that's quite valid.

>IMO because it could interfere with function arg deduction.

How?

In the above example, the argument type can't be deduced,
instead it must be explicitly supplied, e.g.

 int main() {
  cout << square<3>() << endl;
  return 0;
 }

However, that is true whether or not specializations are involved.
In this example, even if only the generic `template <int i> int
square<i>()' version was declared, you would still need to explicitly
supply the argument type.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]