Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
like image 657
ThomasMcLeod Avatar asked Dec 01 '14 21:12

ThomasMcLeod


1 Answers

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.

like image 139
T.C. Avatar answered Nov 15 '22 07:11

T.C.