Topic: const parameters to template class member functions


Author: hosoda@jtec.or.jp (Tokyo Tomy)
Date: Thu, 22 Jul 2004 22:59:22 +0000 (UTC)
Raw View
hosoda@jtec.or.jp (Tokyo Tomy) wrote in message news:<49c1da0b.0407200131.998a680@posting.google.com>...
>...
> How can you do if you want the check argument to be "const int*" to
> accept the original p in the above code.
>
> Following is one solution, but T x becomes  pointer to const int as an
> (probably) undesirable side effect.
>
>...

(continued from my previous post)
Another and better solution is shown below. The lesson herein may be:
Be careful for the combination of pointer and const. When I came
across the solution, I began to think that the behavior ("const T y"
is converted to "T const y") easily brings errors, but is acceptable.

#include <stdio.h>

template<class T>
class myclass {
  T* x;
  public:
  myclass(T* const x0):x(x0) {}

  //int check(T y) { return x==y; }
  int check(const T* y) { return x==y; }
};

int main() {
  int k;
  myclass<int> mc(&k);         // T = int

  const int* p = &k;  // same as in the orginal code

  printf("%d\n",mc.check(p));

  return 0;
}


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

[ 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: eigenmaster@yahoo.com (Kenneth Massey)
Date: Mon, 19 Jul 2004 21:08:54 +0000 (UTC)
Raw View
I have run into a peculiar problem, in which the following sample code
does not compile (gcc 3.3).  I have a template class with a member
function that should take a const version of the template parameter.
However, when I try to use the class with (T=int*), the compiler seems
to ignore the const and gives an error if I pass a const int*.  Any
help would be much appreciated.

Kenneth


#include <stdio.h>

template<class T>
class myclass {
  T x;
 public:
  myclass(T x0):x(x0) {}

  int check(const T y) { return x==y; }

  // compiles fine with this line: T is explicitly replaced by int*
  //  int check(const int* y) { return x==y; }
};

int main() {
  int k;
  myclass<int*> mc(&k);         // T = int*

  const int* p = &k;

  // test.cpp: In function `int main()':
  // test.cpp:25: error: invalid conversion from `const int*' to
`int*'
  // test.cpp:25: error:   initializing argument 1 of `int
myclass<T>::check(T)

  printf("%d\n",mc.check(p));

  return 0;
}


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

[ 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: =?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenberg=29=22?= <dsp@bdal.de>
Date: Tue, 20 Jul 2004 18:12:56 +0000 (UTC)
Raw View
Good morning Kenneth Massey,

Kenneth Massey schrieb:

>I have run into a peculiar problem, in which the following sample code
>does not compile (gcc 3.3).  I have a template class with a member
>function that should take a const version of the template parameter.
>However, when I try to use the class with (T=int*), the compiler seems
>to ignore the const and gives an error if I pass a const int*.  Any
>help would be much appreciated.
>
>Kenneth
>
>
>#include <stdio.h>
>
>template<class T>
>class myclass {
>  T x;
> public:
>  myclass(T x0):x(x0) {}
>
>  int check(const T y) { return x==y; }
>
>  // compiles fine with this line: T is explicitly replaced by int*
>  //  int check(const int* y) { return x==y; }
>};
>
Please note that any template member functions are not automatically
instantiated. You have to
distinguish the point of definition of the template (non-standard
nomenclature) from the actual point of
instantiation (aka POI, just before main in your example).

>int main() {
>  int k;
>  myclass<int*> mc(&k);         // T = int*
>
>  const int* p = &k;
>
>  // test.cpp: In function `int main()':
>  // test.cpp:25: error: invalid conversion from `const int*' to
>`int*'
>  // test.cpp:25: error:   initializing argument 1 of `int
>myclass<T>::check(T)
>
>  printf("%d\n",mc.check(p));
>
>  return 0;
>}
>
Since myclass<int*> does contain an int* member, you are effectivly
trying to
perform a code similar to:

const int* p = &k;
int* x = p;

in your call of ms.check(). This obviously leads to a violation of
constness contraints.

Hope that helps,

Daniel Kr   gler



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

[ 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: Jozef Saniga <jsaniga@hotmail.com>
Date: Wed, 21 Jul 2004 15:26:10 +0000 (UTC)
Raw View
Hi,

Kenneth Massey wrote:
> I have run into a peculiar problem, in which the following sample code
> does not compile (gcc 3.3).  I have a template class with a member
> function that should take a const version of the template parameter.
> However, when I try to use the class with (T=int*), the compiler seems
> to ignore the const and gives an error if I pass a const int*.  Any
> help would be much appreciated.
The compiler does not ignore the const. The const is there just not
where you expect it to be.

> Kenneth
>
>
> #include <stdio.h>
>
> template<class T>
> class myclass {
>   T x;
>  public:
>   myclass(T x0):x(x0) {}
>
>   int check(const T y) { return x==y; }
>
>   // compiles fine with this line: T is explicitly replaced by int*
>   //  int check(const int* y) { return x==y; }
When myclass is instantiated for int* check becomes:
   int check (int* const y) { return x == y; }
since 'const T y' says that y is of type T and y is const. So y is of
type int* and it is const. Note that y is const not the int y points to.
Try to compile this piece of code that has a very similar problem:

int main ()
{
   typedef int* T;
   const T y;
   y = 1;
   return 0;
}

> };
>
> int main() {
>   int k;
>   myclass<int*> mc(&k);         // T = int*
>
>   const int* p = &k;
>
>   // test.cpp: In function `int main()':
>   // test.cpp:25: error: invalid conversion from `const int*' to
> `int*'
>   // test.cpp:25: error:   initializing argument 1 of `int
> myclass<T>::check(T)
>
>   printf("%d\n",mc.check(p));
>
>   return 0;
> }

Jozef


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

[ 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: hosoda@jtec.or.jp (Tokyo Tomy)
Date: Wed, 21 Jul 2004 15:26:10 +0000 (UTC)
Raw View
eigenmaster@yahoo.com (Kenneth Massey) wrote in message news:<ac2b2aa1.0407190619.72a68f9d@posting.google.com>...
> I have run into a peculiar problem, in which the following sample code
> does not compile (gcc 3.3).  I have a template class with a member
> function that should take a const version of the template parameter.
> However, when I try to use the class with (T=int*), the compiler seems
> to ignore the const and gives an error if I pass a const int*.  Any
> help would be much appreciated.
>
> Kenneth
>
>
> #include <stdio.h>
>
> template<class T>
> class myclass {
>   T x;
>  public:
>   myclass(T x0):x(x0) {}
>
>   int check(const T y) { return x==y; }
>
>   // compiles fine with this line: T is explicitly replaced by int*
>   //  int check(const int* y) { return x==y; }
> };
>
> int main() {
>   int k;
>   myclass<int*> mc(&k);         // T = int*
>
>   const int* p = &k;
>
>   // test.cpp: In function `int main()':
>   // test.cpp:25: error: invalid conversion from `const int*' to
> `int*'
>   // test.cpp:25: error:   initializing argument 1 of `int
> myclass<T>::check(T)
>
>   printf("%d\n",mc.check(p));
>
>   return 0;
> }
>

My MSVC++6 also issured the same error just as above.  The
interpretation of the error seems to be easy as follows.

1. "const T y" in the check argument is converted to "T const y", just
like,  for example,"const int i" is equivalent to "int const i".

2. T = int*, so the check argument becomes "int* const y" (const
pointer to int).

After I replaced "const int* p = &k;" with "int* const p = &k;", the
code compiled with my MSVC++6.

However, I just wander you can agree with this behavior.

How can you do if you want the check argument to be "const int*" to
accept the original p in the above code.

Following is one solution, but T x becomes  pointer to const int as an
(probably) undesirable side effect.

#include <stdio.h>

template<class T>
class myclass {
  T x;
  public:
  myclass(T x0):x(x0) {}

  int check(T y) { return x==y; }
};

int main() {
  int k;
  myclass<const int*> mc(&k);         // T = const int*

  const int* p = &k;  // same as in the orginal code
  printf("%d\n",mc.check(p));

  return 0;
}


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

[ 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: gareth_stockwell@hotmail.com (Gareth Stockwell)
Date: Wed, 21 Jul 2004 15:26:10 +0000 (UTC)
Raw View
eigenmaster@yahoo.com (Kenneth Massey) wrote in message news:<ac2b2aa1.0407190619.72a68f9d@posting.google.com>...
> I have run into a peculiar problem, in which the following sample code
> does not compile (gcc 3.3).  I have a template class with a member
> function that should take a const version of the template parameter.
> However, when I try to use the class with (T=int*), the compiler seems
> to ignore the const and gives an error if I pass a const int*.  Any
> help would be much appreciated.

> template<class T>
> class myclass {
>   T x;
>   public:
>     myclass(T x0):x(x0) {}
>     int check(const T y) { return x==y; }
> };


Kenneth,

I think that what is happening here is that, given the signature
  int check(const T);

with T=int*, upon instantiation the compiler is generating
  int check(T* const);
rather than (as you want)
  int check(const T*);

I can think of two solutions:

1. If you know that T will always be some kind of pointer, then
re-write the template such that T is the value type, rather than the
pointer type (so here, T=int).  Then you can write the signature of
check directly:
  int check(const T*);

2. More generally, I think you can get around the problem with a bit
of template metaprogramming.  Basically you need a structure which
converts T to const T and gets the asterix in the correct place...

  template<typename Type>
  struct MakeConst
  { typedef const Type result; };

  template<typename Type>
  struct MakeConst<Type*>
  { typedef const Type* result; };

Now you can write:

  int check(typename MakeConst<T>::result);

Gareth


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

[ 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: Ulrich Eckhardt <doomster@knuut.de>
Date: Wed, 21 Jul 2004 15:26:11 +0000 (UTC)
Raw View
Kenneth Massey wrote:
> I have run into a peculiar problem, in which the following sample code
> does not compile (gcc 3.3).  I have a template class with a member
> function that should take a const version of the template parameter.
> However, when I try to use the class with (T=int*), the compiler seems
> to ignore the const and gives an error if I pass a const int*.  Any
> help would be much appreciated.
>
> #include <stdio.h>
>
> template<class T>
> class myclass {
>   T x;
>  public:
>   myclass(T x0):x(x0) {}
>
>   int check(const T y) { return x==y; }
    ^^^ *ouch*
Don't do that in examples, your real code might have valid reasons to do
so, but not examples.

>   // compiles fine with this line: T is explicitly replaced by int*
>   //  int check(const int* y) { return x==y; }

Yes, but that's something different: assuming T='int*', you have one 'int
const*' and one 'int * const'. If that makes no sense to you, just read
the FAQ, it's explained there.

Uli

--
Questions ?
see  C++-FAQ Lite: http://parashift.com/c++-faq-lite/  first !


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

[ 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: vze2hb3b@verizon.net
Date: Wed, 21 Jul 2004 15:26:11 +0000 (UTC)
Raw View
In comp.lang.c++.moderated Kenneth Massey <eigenmaster@yahoo.com> wrote:
>
> I have run into a peculiar problem, in which the following sample code
> does not compile (gcc 3.3).  I have a template class with a member
> function that should take a const version of the template parameter.
> However, when I try to use the class with (T=int*), the compiler seems
> to ignore the const and gives an error if I pass a const int*.  Any
> help would be much appreciated.
>
> Kenneth
>
>
> #include <stdio.h>
>
> template<class T>
> class myclass {
>  T x;
> public:
>  myclass(T x0):x(x0) {}
>
>  int check(const T y) { return x==y; }
>
>  // compiles fine with this line: T is explicitly replaced by int*
>  //  int check(const int* y) { return x==y; }
> };
>
> int main() {
>  int k;
>  myclass<int*> mc(&k);         // T = int*
>
>  const int* p = &k;

Hi! The problem is that T is int *, so const T translates
to int * const (constant pointer), not to const int *
(pointer to constant integer). If you define p as

int * const p = &k;

then the compiler should be happy.

Best,

Alexander

>
>  // test.cpp: In function `int main()':
>  // test.cpp:25: error: invalid conversion from `const int*' to
> `int*'
>  // test.cpp:25: error:   initializing argument 1 of `int
> myclass<T>::check(T)
>
>  printf("%d\n",mc.check(p));
>
>  return 0;
> }

--
Aleksandr Morgulis
aleksandr.morgulis@verizon.net


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

[ 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: Jeffrey Lau <moodhist@comcast.net>
Date: Wed, 21 Jul 2004 15:26:11 +0000 (UTC)
Raw View
The problem is the placement of the const in the declaration of 'p':
>   int k;
>   myclass<int*> mc(&k);         // T = int*
>
>   const int* p = &k;

If 'T' is 'int*', then 'const T' is 'int* const'; the constant version
of 'int*'. This is perhaps why most template code I have seen will use
'T const' instead of 'const T'. I have also adopted this declaration
style for all const variables in code:

    int const constantInt(5);
    char const* const constantPointerToConstantChar("Blah");

This allows you to read from right to left exactly the type of the
variable.


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

[ 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: Alberto Barbati <AlbertoBarbati@libero.it>
Date: Wed, 21 Jul 2004 15:26:12 +0000 (UTC)
Raw View
Kenneth Massey wrote:
 > I have run into a peculiar problem, in which the following sample code
 > does not compile (gcc 3.3).  I have a template class with a member
 > function that should take a const version of the template parameter.
 > However, when I try to use the class with (T=int*), the compiler seems
 > to ignore the const and gives an error if I pass a const int*.  Any
 > help would be much appreciated.

If you write

    typedef int* T;

Then "const T" is "int* const" (a constant pointer to an int) which is
very different from "const int*" (a pointer to a constant int).

If you analyse your code you will realize that it is a more complex case
of this simple issue.

Alberto


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

[ 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: Christoph Schulz <kristov@arcor.de>
Date: Wed, 21 Jul 2004 19:59:07 +0000 (UTC)
Raw View
Hello!

Kenneth Massey wrote:
> I have run into a peculiar problem, in which the following sample
> code does not compile (gcc 3.3). I have a template class with a
> member function that should take a const version of the template
> parameter. However, when I try to use the class with (T=int*), the
> compiler seems to ignore the const and gives an error if I pass a
> const int*. Any help would be much appreciated.
>
> Kenneth
>
> #include <stdio.h>
>
> template<class T>
> class myclass {
>   T x;
>  public:
>   myclass(T x0):x(x0) {}
>
>   int check(const T y) { return x==y; }
>
>   // compiles fine with this line: T is explicitly replaced by int*
>   //  int check(const int* y) { return x==y; }
> };

The problem is that "const T" is not "const int*" if the template is
instantiated with T=int*, but "int *const". That's similar to:
  typedef int *T;
  typedef const T CT;
Again, CT == "int *const" and *not* "const int*".

>
> int main() {
>   int k;
>   myclass<int*> mc(&k);         // T = int*
>
>   const int* p = &k;
>
>   // test.cpp: In function `int main()':
>   // test.cpp:25: error: invalid conversion from `const int*' to
> `int*'
>   // test.cpp:25: error:   initializing argument 1 of `int
> myclass<T>::check(T)
>
>   printf("%d\n",mc.check(p));
>

Here the compiler tries to use myclass<int*>::check(int *const) and
fails to perform the needed and disallowed conversion "const int*" ==>
"int *const". Of course, if you define a suitable check(const int *),
the compiler error goes away. But again, this has nothing to do with
ignoring const.

Regards,
  Christoph Schulz


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

[ 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                       ]