Search code examples
c++arraysc++11rvalue-reference

C++ using snprintf in ostream with rvalue buffer, is this well-formed?


I was wondering if I could use snprintf formatting in an ostream such that I could embed the call to snprintf in the stream expression itself. This compiles in GCC 4.9, but is it OK?

    cout << [](char (&&buf) [12], int d) { snprintf(buf, 12, "%d", d); return buf; } ({ }, 15) << endl;

Solution

  • This is well-formed and well-defined. {} is used to copy-list-initialize an rvalue reference to char [12], which creates a temporary char [12] array to which the reference is bound. This temporary lives until the end of the full expression - in this case, until the semicolon, so a pointer to an element in the array can be safely returned and used for printing within that expression. (The lambda returns a char * pointing to the first element of this array.)

    Standardese:

    §8.5 [dcl.init]/p17:

    The semantics of initializers are as follows. [...]

    • If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).

    §8.5.4 [dcl.init.list]/p3:

    List-initialization of an object or reference of type T is defined as follows:

    • [...]
    • Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is copy-list-initialized or direct-list-initialized, depending on the kind of initialization for the reference, and the reference is bound to that temporary. [ Note: As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. —end note ]

    §12.2 [class.temporary]/p5:

    A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.