Topic: Premature Array-to-Pointer Decay


Author: "kanze" <kanze@gabi-soft.fr>
Date: Wed, 17 May 2006 11:47:32 CST
Raw View
"Tom   s" wrote:
> I have a short code sample here, and I believe that it should
> compile without warning or error, and that it should print:

> SomeFunc1: Array
> SomeFunc2: Array
> SomeFunc3: Array

> Here's the code:

> #include <cstdlib>
> #include <iostream>
> using std::cout;

> /* 1 */
> void SomeFunc1( double* const p )
> {
>     cout << "SomeFunc1: Pointer\n";
> }

> void SomeFunc1( double (&array)[67] )
> {
>     cout << "SomeFunc1: Array\n";
> }

I'm not sure, but I don't think that there is any way to call
the second without the call being ambiguous.  If I read
   13.3.3.1.1 correctly, array to pointer conversions are
considered an exact match.  (There are a number of special cases
in    13.3.3.2, but none of them seem to apply here.)  If the
parameter type is "double [67]", the call is ambiguous, and in
all other cases (modulo const/volatile qualifiers), the first
function is called.

> /* 2 */
> void SomeFunc2( double* const p )
> {
>     cout << "SomeFunc2: Pointer\n";
> }

> template<unsigned long len>
> void SomeFunc2( double (&array)[len] )
> {
>     cout << "SomeFunc2: Array\n";
> }

A similar problem here: except that there is no ambiguity, since
non-template beats template as a tie breaker.  The template
version will never be called, and there will never be an
ambiguity.

> /* 3 */
> template<class T>
> void SomeFunc3( T* const p )
> {
>     cout << "SomeFunc3: Pointer\n";
> }

> template<class T, unsigned long len>
> void SomeFunc3( T (&array)[len] )
> {
>     cout << "SomeFunc3: Array\n";
> }

This is the interesting case.  IMHO, argument deduction should
succeed for both cases, and the resulting call should be
ambiguous, as in the first case.

> int main()
> {
>     double array[67];
>
>     SomeFunc1(array);
>
>     SomeFunc2(array);
>
>     SomeFunc3(array);
>
>     std::system("PAUSE");
> }

> It won't compile for me with g++  --  I get an ambiguity error
> for the call to SomeFunc1:

> call of overloaded `SomeFunc1(double[67])' is ambiguous
> candidates are: void SomeFunc1(double*)
>                 void SomeFunc1(double (&)[67])

> If I comment-out the call to SomeFunc1, then it compiles
> successfully without error or warning, and prints:

> SomeFunc2: Pointer
> SomeFunc3: Array

> I think the original unaltered code should work as I intended
> it to.

I don't think so.  My version of g++ (4.1.0) agrees with my
analysis above -- it finds both SomeFunc1 and SomeFunc3
ambiguous.

The problem isn't, as you suggest in the subject line, that the
array to pointer conversion is taking place too early, but
simply that it is not taken into consideration in overload
resolution -- it is considered an exact match.

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: Robert Mabee <rmabee@comcast.net>
Date: Wed, 17 May 2006 15:58:37 CST
Raw View
kanze wrote:
> The problem isn't, as you suggest in the subject line, that the
> array to pointer conversion is taking place too early, but
> simply that it is not taken into consideration in overload
> resolution -- it is considered an exact match.

"array IS-A pointer" seems like a really nasty holdover from C
that leads to undiagnosable bugs such as indexing with a pointer
to a base type when the dynamic type is larger.  So, can C++
start evolving towards first-class array types?  As a first step,
breaking the ambiguity by considering array <=> pointer to be a
conversion shouldn't break anything much.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: "kanze" <kanze@gabi-soft.fr>
Date: Thu, 18 May 2006 09:48:40 CST
Raw View
Robert Mabee wrote:
> kanze wrote:
> > The problem isn't, as you suggest in the subject line, that
> > the array to pointer conversion is taking place too early,
> > but simply that it is not taken into consideration in
> > overload resolution -- it is considered an exact match.

> "array IS-A pointer" seems like a really nasty holdover from C
> that leads to undiagnosable bugs such as indexing with a pointer
> to a base type when the dynamic type is larger.  So, can C++
> start evolving towards first-class array types?  As a first step,
> breaking the ambiguity by considering array <=> pointer to be a
> conversion shouldn't break anything much.

C++ has evolved to have first-class array types.  They're
spelled std::vector.  It would be nice if boost::array ended up
in the next version of the standard, but generally speaking, I
don't think C style arrays are fixable.  (Imagine for a moment
the effect on existing code of removing the array-to-pointer
conversion and giving arrays full value semantics.)

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: kuyper@wizard.net
Date: Thu, 18 May 2006 12:46:08 CST
Raw View
Robert Mabee wrote:
.
> "array IS-A pointer" seems like a really nasty holdover from C
> that leads to undiagnosable bugs such as indexing with a pointer
> to a base type when the dynamic type is larger.  So, can C++
> start evolving towards first-class array types?  As a first step,
> breaking the ambiguity by considering array <=> pointer to be a
> conversion shouldn't break anything much.

Backwards compatibility, not just with C, but with C++ itself, means
that any signfifcant movement along that path is just not feasible.
However, there's a different path to avoiding those problems, and C++
has already taken that path: instead of C-style arrays, use C++
containers.There is not, and should not be, any implicit conversion
from the name of std::vector<> object and an iterator referring to it's
first element.

---
[ 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.comeaucomputing.com/csc/faq.html                      ]





Author: NULL@NULL.NULL ("Tom s")
Date: Sun, 14 May 2006 18:51:49 GMT
Raw View
I have a short code sample here, and I believe that it should compile=20
without warning or error, and that it should print:

SomeFunc1: Array
SomeFunc2: Array
SomeFunc3: Array

Here's the code:

#include <cstdlib>
#include <iostream>
using std::cout;

/* 1 */
void SomeFunc1( double* const p )
{
    cout << "SomeFunc1: Pointer\n";
}

void SomeFunc1( double (&array)[67] )
{
    cout << "SomeFunc1: Array\n";
}


/* 2 */
void SomeFunc2( double* const p )
{
    cout << "SomeFunc2: Pointer\n";
}

template<unsigned long len>
void SomeFunc2( double (&array)[len] )
{
    cout << "SomeFunc2: Array\n";
}


/* 3 */
template<class T>
void SomeFunc3( T* const p )
{
    cout << "SomeFunc3: Pointer\n";
}

template<class T, unsigned long len>
void SomeFunc3( T (&array)[len] )
{
    cout << "SomeFunc3: Array\n";
}


int main()
{
    double array[67];
   =20
    SomeFunc1(array);
   =20
    SomeFunc2(array);
   =20
    SomeFunc3(array);
   =20
    std::system("PAUSE");
}


It won't compile for me with g++  --  I get an ambiguity error for the ca=
ll=20
to SomeFunc1:

call of overloaded `SomeFunc1(double[67])' is ambiguous=20
candidates are: void SomeFunc1(double*)=20
                void SomeFunc1(double (&)[67])=20


If I comment-out the call to SomeFunc1, then it compiles successfully=20
without error or warning, and prints:

SomeFunc2: Pointer
SomeFunc3: Array


I think the original unaltered code should work as I intended it to.


-Tom=E1s

---
[ 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.comeaucomputing.com/csc/faq.html                      ]