This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


693. New string types and deprecated conversion

Section: 7.3.3  [conv.array]     Status: CD2     Submitter: Alisdair Meredith     Date: 21 April, 2008

N2800 comment DE 4

[Voted into WP at October, 2009 meeting.]

The deprecated conversion from string literal to pointer to (non-const) character in 7.3.3 [conv.array] paragraph 2 has been extended to apply to char16_t and char32_t types, but not to UTF8 and raw string literals. Is this disparity intentional? Should it be extended to all new string types, reverted to just the original character types, or revoked altogether?

Additional places in the Standard that may need to change include 14.2 [except.throw] paragraph 3 and 12.2.4.3 [over.ics.rank] paragraph 3.

Additional discussion (August, 2008):

The removal of this conversion for current string literals would affect overload resolution for existing programs. For example,

    struct S {
        S(const char*);
    };
    int f(char *);
    int f(X);
    int i = f("hello");

If the conversion were removed, the result would be a quiet change in behavior. Another alternative to consider would be a required diagnostic (without making the program ill-formed).

Notes from the September, 2008 meeting:

The CWG agreed that the deprecated conversion should continue to apply to the literals to which it applied in C++ 2003. Consensus was not reached regarding whether it should apply only to those literals or to all the new literals as well, although it was agreed that the current situation in which it applies to some, but not all, of the new literals is unacceptable.

Notes from the July, 2009 meeting:

The CWG reached consensus that the deprecated conversion should be removed altogether.

Proposed resolution (September, 2009):

  1. Remove 7.3.3 [conv.array] paragraph 2:

  2. A string literal (5.13.5 [lex.string]) with no prefix, with a u prefix, with a U prefix, or with an L prefix can be converted to an rvalue of type “pointer to char”, “pointer to char16_t”, “pointer to char32_t”, or “pointer to wchar_t”, respectively. In any 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 Clause Annex D [depr]. —end note] For the purpose of ranking in overload resolution (12.2.4.2.2 [over.ics.scs]), this conversion is considered an array-to-pointer conversion followed by a qualification conversion (7.3.6 [conv.qual]). [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]
  3. Delete the indicated text from the third sub-bullet of the first bullet of paragraph 3 of 12.2.4.3 [over.ics.rank]:

  4. Delete the note from 14.2 [except.throw] paragraph 3 as follows:

  5. A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively. [Note: the temporary object created for a throw-expression that is a string literal is never of type char*, char16_t*, char32_t*, or wchar_t*; that is, the special conversions for string literals from the types “array of const char”, “array of const char16_t”, “array of const char32_t”, and “array of const wchar_t” to the types “pointer to char”, “pointer to char16_t”, “pointer to char32_t”, and “pointer to wchar_t”, respectively (7.3.3 [conv.array]), are never applied to a throw-expression. —end note] The temporary is an lvalue...
  6. Change the discussion of 5.13.5 [lex.string] in C.6.2 [diff.lex] as follows:

  7. Change: String literals made const
    The type of a string literal is changed... “array of const wchar_t.”

        char* p = "abc";   // valid in C, invalid in C++
    
    

    ...

    Difficulty of converting: Simple syntactic transformation, because string literals can be converted to char*; (7.3.3 [conv.array]). The most common cases are handled by a new but deprecated standard conversion Syntactic transformation. The fix is to add a cast:

      char* p = "abc";                // valid in C, deprecated in C++
      char* q = expr ? "abc" : "de";  // valid in C, invalid in C++
      void f(char*) {
          char* p = (char*)"abc";  // cast added
          f(p);
          f((char*)"def");         // cast added
       }
    
  8. Delete _N3000_.D.4 [depr.string]:

  9. D.4 Implicit conversion from const strings [depr.string]

    The implicit conversion from const to non-const qualification for string literals (7.3.3 [conv.array]) is deprecated.