Topic: function template specialization


Author: Nathan Sidwell <nathan@cs.bris.ac.uk>
Date: 1998/02/13
Raw View
Hi,
I've a problem with specializing a template function. the problem
manifests itself with arrays, (which don't decay to pointers in
templates). So for template instatiation, "a", "ab" etc are different
types. I cannot figure out how to specialize a template to deal with
arrays of arbitrary length. Here is some code to show what happens,

#include <stdio.h>

template<class T> int func(T obj)
{
  return 0;
}

int func(char)
{
  return 1;
}

int func(char const [])
{
  return 2;
}

int main()
{
  printf("func('c') = %d\n", func('c'));
  printf("func(5) = %d\n", func(5));
  printf("func((char const *)\"s\") = %d\n", func((char const *)"s"));
  printf("func(\"s\") = %d\n", func("s"));

  return 0;
}

compiling with both g++ 2.6.3 and SUN CC 4.0 produces an executable
which outputs

nathan@laie:442>./foo
func('c') = 1
func(5) = 0
func((char const *)"s") = 2
func("s") = 0

the first and second calls select the char specialization and an
implicit int instatiation, as I expected. but the last two calls select
different functions, which is not what I want.

What I want to be able to do is have func((char const *)"s") and
func("s") select the same specialization, but I can't figure it out.

How do I do this? Having a type system where different length arrays are
different types is plainly wrong, as discovered in Pascal.

nathan
--
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
      You can up the bandwidth, but you can't up the speed of light
nathan@acm.org  http://www.cs.bris.ac.uk/~nathan/  nathan@cs.bris.ac.uk


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Edward Diener <eddielee@abraxis.com>
Date: 1998/02/15
Raw View
A string constant, ie. "s", is a char *, not a const char *. The reason
Stroustrup gives for this is that making a string constant a const char *
would have broken alot of older code. Therefore in your example you need a
specialization for char * to mimic the const char * specialization if you
want your 3rd and 4th printfs to act the same.

Nathan Sidwell wrote:

> Hi,
> I've a problem with specializing a template function. the problem
> manifests itself with arrays, (which don't decay to pointers in
> templates). So for template instatiation, "a", "ab" etc are different
> types. I cannot figure out how to specialize a template to deal with
> arrays of arbitrary length. Here is some code to show what happens,
>
> #include <stdio.h>
>
> template<class T> int func(T obj)
> {
>   return 0;
> }
>
> int func(char)
> {
>   return 1;
> }
>
> int func(char const [])
> {
>   return 2;
> }
>
> int main()
> {
>   printf("func('c') = %d\n", func('c'));
>   printf("func(5) = %d\n", func(5));
>   printf("func((char const *)\"s\") = %d\n", func((char const *)"s"));
>   printf("func(\"s\") = %d\n", func("s"));
>
>   return 0;
> }
>
> compiling with both g++ 2.6.3 and SUN CC 4.0 produces an executable
> which outputs
>
> nathan@laie:442>./foo
> func('c') = 1
> func(5) = 0
> func((char const *)"s") = 2
> func("s") = 0
>
> the first and second calls select the char specialization and an
> implicit int instatiation, as I expected. but the last two calls select
> different functions, which is not what I want.
>
> What I want to be able to do is have func((char const *)"s") and
> func("s") select the same specialization, but I can't figure it out.
>
> How do I do this? Having a type system where different length arrays are
> different types is plainly wrong, as discovered in Pascal.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Daniel Parker" <danielp@nospam.com>
Date: 1998/02/15
Raw View
-----Original Message-----
From: Nathan Sidwell <nathan@cs.bris.ac.uk>
Newsgroups: comp.std.c++
Date: Friday, February 13, 1998 4:41 PM
Subject: function template specialization

>I've a problem with specializing a template function. .. Here is some code
to show what happens,
>
>compiling with both g++ 2.6.3 and SUN CC 4.0 produces an executable
>which outputs
>
>nathan@laie:442>./foo
>func('c') = 1
>func(5) = 0
>func((char const *)"s") = 2
>func("s") = 0


I attempted this on VC++ 5 (with Service Pack 3), using the following
version of the code which I was sure would work:

template<class T>
int func(T obj)
{
  return 0;
}

int func(char)
{
  return 1;
}

int func(const char *)
{
  return 2;
}

void test1()
{
  printf("func('c') = %d\n", func('c'));
  printf("func(5) = %d\n", func(5));
  printf("func((char const *)\"s\") = %d\n", func((const char*)"s"));
  printf("func(\"s\") = %d\n", func("s"));
}

It didn't, I got the same results as Nathan.  I then changed the definition
of the function to

template<class T>
int func( const T& obj )
{
  return 0;
}

and it worked, the results were 1, 0, 2, 2 as expected.  Not that I have any
idea why.  Comments?

--
Please do not use reply, use danielp@anabasis.com instead.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: ncm@nospam.cantrip.org (Nathan Myers)
Date: 1998/02/15
Raw View
Edward Diener <eddielee@abraxis.com> wrote:
>A string constant, ie. "s", is a char *, not a const char *. The reason
>Stroustrup gives for this is that making a string constant a const char *
>would have broken alot of older code. Therefore in your example you need a
>specialization for char * to mimic the const char * specialization if you
>want your 3rd and 4th printfs to act the same.

This is wrong, of course.  A string literal, "s", is an array.
However, is no ordinary array, but a special unnameable type used
only for string literals, and which decays to a regular array,
a char const*, or a char*, according to what you are trying to do
with it.  Of course not all compilers conform to this yet, but they
will eventually.

If your compiler supports function template overloading you can
match the array and find out its size with something like this
(if I remember my antichrist-declaration-syntax correctly):

  template <typename T, size_t N>
    void f(T (const& a)[N]) { cout << N << "\n"; }

Sorry, I don't have my EDG-based compiler handy to try it at the
moment, but I'm sure somebody will correct me if it's wrong.

String literals are another area where C-compatibility was allowed
to make C++ more complicated than would otherwise be necessary.

Nathan Myers
ncm@nospam.cantrip.org  http://www.cantrip.org/
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Edward Diener <eddielee@abraxis.com>
Date: 1998/02/17
Raw View
You're absolutely right. Thanks for waking me up about this. I rechecked
Stroustrup 3 and had misread the type of a string literal or forgot what I had
read.

Nathan Myers wrote:

> Edward Diener <eddielee@abraxis.com> wrote:
> >A string constant, ie. "s", is a char *, not a const char *. The reason
> >Stroustrup gives for this is that making a string constant a const char *
> >would have broken alot of older code. Therefore in your example you need a
> >specialization for char * to mimic the const char * specialization if you
> >want your 3rd and 4th printfs to act the same.
>
> This is wrong, of course.  A string literal, "s", is an array.
> However, is no ordinary array, but a special unnameable type used
> only for string literals, and which decays to a regular array,
> a char const*, or a char*, according to what you are trying to do
> with it.  Of course not all compilers conform to this yet, but they
> will eventually.
>
> If your compiler supports function template overloading you can
> match the array and find out its size with something like this
> (if I remember my antichrist-declaration-syntax correctly):
>
>   template <typename T, size_t N>
>     void f(T (const& a)[N]) { cout << N << "\n"; }
>
> Sorry, I don't have my EDG-based compiler handy to try it at the
> moment, but I'm sure somebody will correct me if it's wrong.
>
> String literals are another area where C-compatibility was allowed
> to make C++ more complicated than would otherwise be necessary.
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]