Home  >  Article  >  Backend Development  >  Does STL Method Chaining Preserve Evaluation Order in C ?

Does STL Method Chaining Preserve Evaluation Order in C ?

Patricia Arquette
Patricia ArquetteOriginal
2024-10-24 03:28:01501browse

Does STL Method Chaining Preserve Evaluation Order in C  ?

Does Chaining STL Methods in C Preserve Evaluation Order?

In Bjarne Stroustrup's "The C Programming Language" 4th edition, the following code snippet exemplifies method chaining:

<code class="cpp">void f2() {
  std::string s = "but I have heard it works even if you don't believe in it";
  s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
  assert(s == "I have heard it works only if you believe in it");
}</code>

This code evaluates statements from left to right, altering the string s incrementally. However, the behavior of this expression is ambiguous depending on the compiler used:

  • Clang: Evaluation follows the expected order, resulting in s as "I have heard it works only if you believe in it".
  • GCC: The evaluation order is unpredictable, causing s to take on an incorrect value.
  • Visual Studio: Similar to GCC, the evaluation is ambiguous, often producing the same incorrect result.

Unveiling the Unspecified Behavior

The code exhibits unspecified behavior because of the indeterminate order of evaluation of subexpressions, despite not invoking undefined behavior. The crux of the issue lies in the evaluation order of function arguments within chained function calls.

Specifically, for the following sub-expressions:

  • s.find("even")
  • s.find(" don't")

Their evaluation order is indeterminate with respect to:

  • s.replace(0, 4, "")

This means that the find calls can be evaluated before or after the replace call, affecting the length of s and consequently altering the results of the find calls.

Illustration with Custom Find Function

To demonstrate this ambiguity, a modified version of the code uses a custom my_find function that reports the position of the search strings in each sub-expression evaluation:

<code class="cpp">std::string::size_type my_find(std::string s, const char *cs) {
  std::string::size_type pos = s.find(cs);
  std::cout << "position " << cs << " found: " << pos << std::endl;
  return pos;
}</code>

Running this code with different compilers yields different results depending on the evaluation order:

  • Clang: my_find is evaluated for "even" before it is evaluated for "don't," resulting in the correct output.
  • GCC: my_find is evaluated for "don't" before it is evaluated for "even," leading to an incorrect result.

C 17 Changes

The C 17 standard (p0145r3) introduces refinements to the expression evaluation order rules to address this ambiguity. It strengthens the order of evaluation for postfix-expressions and their expression-list as follows:

  • The postfix-expression is sequenced before each expression in the expression-list and any default argument.

This ensures that chained method calls evaluate in the expected order, resolving this undefined behavior in C 17.

The above is the detailed content of Does STL Method Chaining Preserve Evaluation Order in C ?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn