Subject: Re: Template argument deduction question
From: Daveed Vandevoorde <[email-masked]>
To: David Abrahams <[email-masked]>
Cc: [email-masked]
Date: Fri, 3 Jun 2005 16:47:37 -0400

On Jun 3, 2005, at 9:47 AM, David Abrahams wrote:

> The following message is a courtesy copy of an article
> that has been posted to gmane.comp.lib.boost.devel as well.
>
> Vladimir Prus <[email-masked]> writes:
>
>> David Abrahams wrote:
>>
>>>> Below is the test program:
>>>>
>>>>
>>>>     char* cmdline3_[1] = {};
>>>>
>>>>     template<class charT>
>>>>     void func(const charT* const argv[]) {}
>>>>
>>>>     int main()
>>>>     {
>>>>         // P is 'const charT* const argv[]'cmdline3_
>>>>         // A is 'char* cmdline3_[]'
>>>
>>> I think A is   'char*[1]'
>>
>> Yes, but it still should be converted to char** for template argument
>> deduction.
>>
>>>>         // According to 14.8.2.1/2
>>>>         // If P is not reference type
>>>>         //    -If A is an array type, the pointer type produced
>>>>         //     by the array-to-pointer standard convertion (4.2)
>>>>         //     is used in place of A for type deduction.
>>>>         //
>>>>         // So, A should become 'char**'
>>>>
>>>>         // The following does not compile.
>>>>         func(cmdline3_);
>>>>
>>>>         char** p = cmdline3_;
>>>>         // This does compile, even though the argument type used for
>>>>         // type deduction should be the same as in example above.
>>>>         func(p);
>>>>
>>>>     }
>>>>
>>>> Anybody can explain what's going on?
>>>
>>> It's well known that converting a char** into a char const** is a
>>> type-safety hole, so the language doesn't allow it (see D&E for the
>>> details, I think).
>>
>> I know that. What's why the function argument is not (const charT* 
>> argv[])
>> but (const charT* const argv[])
>>
>>> 'char*[1]' converts (by array-to-pointer) to 'char**',
>>> but a 'const charT* const[]' parameter is equivalent to char const*
>>> const*', so a similar logic applies.
>>
>> I don't think so. In the second call, passing "char**" to the same 
>> function
>> works without any problems. It looks like in the first call, compiler
>> "forgets" to promote array to pointer.
>
> On second thought, I think you've found an EDG bug.

First, we agree that the two calls should make the same
target selection.  Unfortunately, that doesn't just fall
out of a literal reading of the standard.  We've opened
a Core issue to clarify that this should be the case.

The part of the standard that isn't entirely clear is
14.8.2.1/4 (two paragraphs after the one quoted).  It
specifies that normally the deduced type and the type A
transformed as "above" (i.e., as per the quoted
14.8.2.1/2) should end up identical.  However, they
are not identical in this case: There are cv-qualification
differences.  For the second call, the second bullet of
14.8.2.1/4 applies unambiguously.  However, for the first
call type A is still "char*[1]" (the note that the type
should be "transformed as above" first, isn't repeated
here) and so the bullet doesn't apply since that is not
a pointer type.

Cheers,

	Daveed Vandevoorde
	Edison Design Group