Topic: Function template argument deduction for string literals


Author: "=?iso-8859-1?q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Thu, 25 Jan 2007 15:43:39 CST
Raw View
Hello,

recently I stumbled across the example given in 14.8.1 paragraph 3
of [temp.arg.explicit]:

template<class X, class Y, class Z> X f(Y,Z);
void g()
{
    f<int,char*,double>("aa",3.0);
    f<int,char*>("aa",3.0); // Z is deduced to be double
    f<int>("aa",3.0);         // Y is deduced to be char*, and
                                    // Z is deduced to be double
    f("aa",3.0);                 //error: X cannot be deduced
}

Please consider the third function invocation and its comment
"Y is deduced to be char* [..]".

I'm aware that comments in Our Holy Standard are non-normative,
but I'm quite sure that this assertion is wrong and should be fixed.
I got to this impression when I tried to get the proper answer to the
question "What should be Y deduced to?" in this situation, which
usually is a simple task for other literals. But my self-confidence
became smaller when I tried to follow a reasoning given by
Nathan Myers in http://tinyurl.com/yrwxz2 (which discusses a
different function template form, but his basic type deduction
argumentation should apply here).

I do have high respect in Nathan Myers, but can I really conclude
from this reasoning that a proper compiler should indeed deduce
Y to be of an artifical type named 'literal char[3]'?

Indeed my own research for "string literal" in ISO 14882:2003(E)
first brought me to his very same quote:

2.13.4 p. 1 says:

"An ordinary string literal has type "array of n const char" and
static storage duration (3.7), where n is the size of the string
as defined below, and is initialized with the given characters."

This sentence seems to be so clear, that I don't see any
reasons why Y should differ from the expected result
'array of 3 const char'. OK, lets go on.

I'm aware that 4.2 p. 2 speaks about possible conversions of
string literals, but can someone explain to my why its wordings:

"A string literal (2.13.4) that is not a wide string literal can be
converted to an rvalue of type "pointer to char"; a wide string
literal can be converted to an rvalue of type "pointer to wchar_t".

In either case, the result is a pointer to the first element of the
array.
This conversion is considered only when there is an explicit
appropriate pointer target type, and not when there is a general
need to convert from an lvalue to an rvalue. [Note: this conversion
is deprecated. See Annex D. -end note ] For the purpose of
ranking in overload resolution (13.3.3.1.1), this conversion is
considered an array-to-pointer conversion followed by a
qualification conversion (4.4). [ Example: "abc" is converted to
"pointer
to const char" as an array-to-pointer conversion, and then to
"pointer
to char" as a qualification conversion. -end example ]"

should be relevant here?
I'm not a natively English speaking person, so I would like to ask:

Does the above given description indeed say, that overload deduction
*must* use array-to-pointer conversion for string-literals?

Why is Identity conversion not OK and what would be the result
of such an Identity conversion for string literals?

Is the main reason for this extra-ordinary position of string
literals a result of the fact that they are l-values according to
5.1 p. 2 (which is indeed an exception among literals)?
But where says the standard that l-values *must* perform an
l-value->r-value transformation to get the proper result of this
type deduction?

I have to confess that I don't see a conclusive argumentation
concerning this issue in the standard, although e.g. Comeau
and VS2005 SP1 seem to agree that Y is "const char*" and
not "const char[3]" as I had argued mainly based on 2.13.4,
because the words of 4.2 did not seem to be mandatory for
me in this example. (Note: This is only an indirect conclusion
based on compiler output during an error message
enforcement in this example.)

At the very end I would say, that the quoted example should
be wrong and I would appreciate to see the proper words for
its resolution - most probably for the benefit for the C++
community ;-)

Greetings from Bremen,

Daniel Kr   gler


---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 25 Jan 2007 22:31:56 GMT
Raw View
Daniel Kr=FCgler wrote:
> At the very end I would say, that the quoted example should
> be wrong

I don't see how the standard could be any clearer.

14.8.2.1 says
     1 Template argument deduction is done by comparing each
       function template parameter type (call it P) with the
       type of the corresponding argument of the call (call
       it A) as described below.
     2 If P is not a reference type:
       =97 If A is an array type, the pointer type produced by
         the array-to-pointer standard conversion (4.2) is
         used in place of A for type deduction;

---
[ 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: "=?iso-8859-1?q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Fri, 26 Jan 2007 09:36:43 CST
Raw View

On Jan 25, 11:31 pm, hyro...@mail.com (Hyman Rosen) wrote:
> Daniel Kr   gler wrote:
> > At the very end I would say, that the quoted example should
> > be wrongI don't see how the standard could be any clearer.
>
> 14.8.2.1 says
>      1 Template argument deduction is done by comparing each
>        function template parameter type (call it P) with the
>        type of the corresponding argument of the call (call
>        it A) as described below.
>      2 If P is not a reference type:
>        - If A is an array type, the pointer type produced by
>          the array-to-pointer standard conversion (4.2) is
>          used in place of A for type deduction;

Thanks for this quotation. I only looked for string literals in the
standard, and its a shame that I did not consider this obvious
place.

But what is your opinion concerning the validity of the quoted
example text? Your silence implies to me that you assume
that it is valid (?).

Based on your proof that array-to-pointer conversion must be done,
shouldn't the combination with 13.3.3.2 p. 3

"S1 and S2 differ only in their qualification conversion and yield
similar types T1 and T2 (4.4), respectively, and the cv-qualification
signature of type T1 is a proper subset of the cv-qualification
signature of type T2, and S1 is not the deprecated string literal
array-to-pointer conversion (4.2)."

lead to conclusion that Y has to be deduced to 'const char*',
which is also the result given by Comeau and others? In this case
I'm right and the (non-normative) standard text is wrong, otherwise
Comeau and VS2005 would wrong.

Greetings from Bremen,

Daniel Kr   gler


---
[ 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: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 26 Jan 2007 17:00:28 GMT
Raw View
Daniel Kr=FCgler wrote:
> But what is your opinion concerning the validity of the quoted
> example text? Your silence implies to me that you assume
> that it is valid (?).

Oh, sorry. I was thinking about whether the array-to-pointer
conversion was needed, not about the lack of const. I do agree
that the deduced type should be 'char const *', not 'char *'
and that the example is wrong. 4.2/2 seems to make that clear,
saying that the conversion to 'char *' happens only when the
target is explicitly 'char *', not just generally.

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