18

I was reading these two paragraphs of the FDIS (12.2p{4,5}):

There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is when a default constructor is called to initialize an element of an array. If the constructor has one or more default arguments, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any.

and

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except: [...]

  • 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.

These two two seem to contradict for the following case

struct A {
  A() { std::cout << "C" << std::endl; }
  ~A() { std::cout << "D" << std::endl; }
};

struct B {
  B(A const& a = A()) { }
};

typedef B array[2];

int main() {
  array{};
}

Will this output CDCD as required by the first context, or will this output CCDD as required by the second context? GCC seems to follow the second context description and outputs CCDD. Have I overlooked something important?


EDIT: I don't think it needs C++0x. This new-expression is affected too by my question:

new array(); /* CDCD or CCDD ?? */

In this case though, GCC follows the first context, and outputs CDCD.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Reported, in the hope that some GCC developer comments on it: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49372 – Johannes Schaub - litb Jun 11 '11 at 13:47
  • Weird: my GCC 4.6 outputs nothing. -- ah, I see you have the same seemingly wrong behavior :) For what it's worth: MSVS2010 SP1 outputs CDCD... – rubenvb Jun 11 '11 at 13:49
  • Also: 8.5.4/4 seems to imply there are *ordinarily* no sequencing constraints on the arguments of a call. Is that relevant here, because the `new array()` case in GCC prints `CDCD`? – rubenvb Jun 11 '11 at 14:12
  • As I see it's a defect (in the standard's draft). But it's one of those defects that do not matter much in practice. :-) – Cheers and hth. - Alf Jun 12 '11 at 18:08

1 Answers1

2

I don't think there's a contradiction.

5.2.2 clearly says what a function call is. A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of expressions which constitute the arguments to the function.

There doesn't seem to be a function call to B::B(A const&) anywhere in your program, so I don't see how the second passage applies.

EDIT the above is probably incorrect, given 1.9p10 etc.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • 1
    While I agree it's sometimes a bit unclear, a "function call" in C++ is not restricted to the syntax specified by 5.2.2. It's just the call of a function, which might use any and all syntax and can also be implicit. See the note at 1.9p15 "Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: Evaluation of a new expression invokes one or more allocation and constructor functions; see 5.3.4. ... -- end example]". – Johannes Schaub - litb Jun 11 '11 at 20:08
  • Most of 5.2.2 applies generally to calls to functions, disregarding the context necessitating the function call. The bullet I quoted may only intend to apply when explicitly the function call syntax is used (I think there is some room for misinterpretation here, which is unfortunate. Especially because of the crossreference to 5.2.2), but that would seem to be weird, because it would mean that many expression template nodes would cause undefined behavior (because they only keep references to the arguments passed to their constructors and reference them long after their ctors run). – Johannes Schaub - litb Jun 11 '11 at 20:12
  • @johannes I would say there's indeed an unfortunate wording, as there's indeed very little difference between a function call and, say, an operator invocation. But implicit calls are different. An implicit call is not an expression, hence, not a part of any full expression. Sometimes there's no expelression at all to associate with such call (e.g. in a declaration conrltext). So I still think the second context does not apply. – n. m. could be an AI Jun 12 '11 at 00:38
  • 2
    1.9p10 applies: "A full-expression is an expression that is not a subexpression of another expression. If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition.". Note that in my example, `array{}` is an expression already (functional cast), as is `new array()` (new-expression). – Johannes Schaub - litb Jun 12 '11 at 00:42
  • @JohannesSchaub-litb In the paragraph that you quoted, does "a use of the language construct is considered to be an expression" mean that the construct itself is an expression or the implicit call is an expression? This question started when I saw the comment in the following code sample from the same paragraph: `S s1(1); // full-expression is call of S​::​S(int)`. I also formulated this in a stackoverflow question: https://stackoverflow.com/questions/45744673/c-full-expression-standard-wording. Thank you. – user42768 Aug 19 '17 at 10:07