Matching template argument types with cv-qualifiers

Matching template argument types with cv-qualifiers

Post by Shmulik Fli » Sat, 23 Nov 2002 04:14:54



Please look at the following code:

template <class T> class MyClass {};
void f(MyClass<const int> x) {}

int main()
{
    MyClass<int> x;
    f(x);

    return 0;

Quote:}

VC++ 6.0 rejects this code with the following error:
error C2664: 'f' : cannot convert parameter 1 from 'class
MyClass<int>' to 'class MyClass<int const >'
No constructor could take the source type, or constructor overload
resolution was ambiguous

Other Unix compilers seem to except it.

Which compiler is right? Please give a reference to the standard which
explicitly say so. I couldn't find any.


      [ about comp.lang.c++.moderated. First time posters: do this! ]

 
 
 

Matching template argument types with cv-qualifiers

Post by Jerry Coffi » Sat, 23 Nov 2002 19:20:30




 > Please look at the following code:

[ ... ]

 > VC++ 6.0 rejects this code with the following error:
 > error C2664: 'f' : cannot convert parameter 1 from 'class
 > MyClass<int>' to 'class MyClass<int const >'
 > No constructor could take the source type, or constructor overload
 > resolution was ambiguous
 >
 > Other Unix compilers seem to except it.
 >
 > Which compiler is right? Please give a reference to the standard which
 > explicitly say so. I couldn't find any.

Microsoft is right.  I suppose the real bottom line of what says so
is section 5/2 -- you've called a function with a particular type of
parameter, and there's no prototype in scope for a function with that
signature, so your program is ill-formed.

Why that's true is pretty simple: there is an implicit conversion
from X to const X (for example) as a parameter by itself (at least
for all built-in types), but that does not imply that there is any
implicit or automatic conversion from templ_class<X> to templ_class
<const X>.  The latter two are totally unrelated unless you define a
conversion to handle the job.

I'm a bit surprised that your other compilers accept this unless
you're using relatively old versions.  Most recent compilers I've
used (for any platform) have rejected it as they should.  Just for
example, GNU C++ 3.2 rejects it, and I'd be a bit surprised if this
was the first version to do so either.

--
     Later,
     Jerry.

The universe is a figment of its own imagination.


      [ about comp.lang.c++.moderated. First time posters: do this! ]

 
 
 

Matching template argument types with cv-qualifiers

Post by Shinji Ika » Sat, 23 Nov 2002 19:22:57


 > Please look at the following code:
 >
 > template <class T> class MyClass {};
 > void f(MyClass<const int> x) {}
 >
 > int main()
 > {
 >     MyClass<int> x;
 >     f(x);
 >
 >     return 0;
 > }
 >

You are missing the const qualifier in the declaration of x.  You
should have written:

     MyClass<const int> x;
     f(x);


      [ about comp.lang.c++.moderated. First time posters: do this! ]

 
 
 

Matching template argument types with cv-qualifiers

Post by AndrĂ© P?nit » Sat, 23 Nov 2002 19:48:40


 > void f(MyClass<const int> x) {}
 >
 >  MyClass<int> x;

 > VC++ 6.0 rejects this code with the following error:
 > error C2664: 'f' : cannot convert parameter 1 from 'class
 > MyClass<int>' to 'class MyClass<int const >'
 > No constructor could take the source type, or constructor overload
 > resolution was ambiguous

And correctly so. MyClass<const int> and MyClass<int> are different types
and there is no conversion defined.

 > Other Unix compilers seem to except it.

Which ones?

 > Which compiler is right? Please give a reference to the standard which
 > explicitly say so. I couldn't find any.

Hm. Perhaps something like

14.2.6 A template-id that names a class template specialization is  a
classname.

Andre'

--
Those who desire to give up Freedom in order to gain Security,
will not have, nor do they deserve, either one. (T. Jefferson)


      [ about comp.lang.c++.moderated. First time posters: do this! ]

 
 
 

Matching template argument types with cv-qualifiers

Post by John H. Spice » Sat, 23 Nov 2002 19:56:45


 > Please look at the following code:
 >
 > template <class T> class MyClass {};
 > void f(MyClass<const int> x) {}
 >
 > int main()
 > {
 >     MyClass<int> x;
 >     f(x);
 >
 >     return 0;
 > }
 >
 > VC++ 6.0 rejects this code with the following error:
 > error C2664: 'f' : cannot convert parameter 1 from 'class
 > MyClass<int>' to 'class MyClass<int const >'
 > No constructor could take the source type, or constructor overload
 > resolution was ambiguous
 >
 > Other Unix compilers seem to except it.
 >
 > Which compiler is right? Please give a reference to the standard which
 > explicitly say so. I couldn't find any.

The code is invalid and I've yet to find a compile that accepts this code.

MyClass<const int> and MyClass<int> are different types with no user-defined
converions between them, so the call is not valid.

John Spicer
Edison Design Group


      [ about comp.lang.c++.moderated. First time posters: do this! ]

 
 
 

Matching template argument types with cv-qualifiers

Post by dsto » Sun, 24 Nov 2002 13:54:58


Hi Shmulik,

I tried your code with aCC, aCC -AA and g++, and it didn't work, which
did not really surprised me.
Whatever the link between 2 types "T1" and "T2", wheteher "T1" can be
converted into "T2" or reverse, template instantiations with "T1" and
"T2" are to my understanding completely unrelated. In you case:
- an "int" can be cast into a "const int".
- a "MyClass<int>" has NO connection with "MyClass<const int>"; there
do not 'inherit' any relationship from the relationship that can exist
between "int" and "const int", otherwise explicitly mentionned.

The only implicit conversion I found mentioned in the standard (but I
am not a specialist of the standard) is about non-type template
parameters (14.3.2).

If you want to enable the conversion from "MyClass<T>" to
"MyClass<const T>", you can do the following:

   template <class T>
   class MyClass
   {};
   // Specialization for const types
   template <class T>
   class MyClass<const T>
   {
   public:
      // Constructor from a "MyClass<T>", which also defines a
conversion
      MyClass(const MyClass<T> & x)
      {}
   };

   void f(MyClass<const int> x)
   {}

   int main()
   {
      MyClass<int> x;
      f(x); // Now, it works!

      return 0;
   }

Dan STORA.


> Please look at the following code:

> template <class T> class MyClass {};
> void f(MyClass<const int> x) {}

> int main()
> {
>     MyClass<int> x;
>     f(x);

>     return 0;
> }

> VC++ 6.0 rejects this code with the following error:
> error C2664: 'f' : cannot convert parameter 1 from 'class
> MyClass<int>' to 'class MyClass<int const >'
> No constructor could take the source type, or constructor overload
> resolution was ambiguous

> Other Unix compilers seem to except it.

> Which compiler is right? Please give a reference to the standard which
> explicitly say so. I couldn't find any.


      [ about comp.lang.c++.moderated. First time posters: do this! ]
 
 
 

Matching template argument types with cv-qualifiers

Post by Francis Glassboro » Sun, 24 Nov 2002 14:01:47



writes

Quote:>MyClass<const int> and MyClass<int> are different types with no user-defined
>converions between them, so the call is not valid.

Which is a feature of templates that needs to be better understood by
programmers. OTOH perhaps we need to consider whether there is a good
mechanism for providing a relationship between templates whose template
arguments are closely related (cv qualified types and reference types)

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


      [ about comp.lang.c++.moderated. First time posters: do this! ]

 
 
 

1. top-level cv-qualifiers on template-parameter ignored

In draft 2 Dec 96, Section 14.1/4 states

"The top-level cv-qualifiers on the template-parameter are
ignored when determining its type."

Consider the following example:

template<class T> class c {public: typedef T t;};
template<class T> class d {public: typedef T t;};
void f() {
    int i;
    c<int>::t* ci=&i;        // 1 int* ci=&i;
    *ci = 0;                 // 2 ok
    c<const int>::t* cci=&i; // 3 const int* cci=&i;
    *cci = 0;                // 4 ?no error?
    d<const int>::t* dci=&i; // 5 const int* dci=&i;
    *dci = 0;                // 6 error, l-value specifies const object
    d<int>::t* di=&i;        // 7 int* di=&i;
    *di = 0;                 // 8 ?error, l-value specifies const
object?

MSVC++ 5.0 generates no error for line 4 and
an error for line 8, opposite of what I expected.

Apparently VC++ ignores the cv-qualifiers, but only
after the first instantiation.

1. Is the behaviour correct per standard?

2. Why is rule 14.1/4 included in the standard?

This issue is relevant to the design of smart pointers.
Similar problems occur when smart pointers are constructed
whose template parameters differ only in cv-qualifiers.

Mike Schuster


      [ about comp.lang.c++.moderated. First time posters: do this! ]

2. Counting Distinct values - with a twist SOLVED

3. cv-qualifiers on function parameters passed by value

4. *** Modem for Mac PowerBook ***

5. accessor cv-qualifiers

6. Wanted Amiga Magazines Cover CDs in UK

7. CV-Qualifiers

8. VisualDSP++ iir() problems

9. Defect Report: cv qualifiers on function types

10. Cv-qualification of deduced template arguments

11. cv overloading and template argument deduction

12. cv-quals in template arguments