Are there sequence points in braced initializer lists when they apply to constructors?

前端 未结 2 634
青春惊慌失措
青春惊慌失措 2020-12-10 01:31

According to the n4296 C++ standard document:

[dcl.init.list] (8.5.4.4) (pg223-224)

Within the initializer-list of a braced-init-list, the

相关标签:
2条回答
  • 2020-12-10 02:18

    The answer seems to be that yes, this is a bug in both GCC and MSVC.

    This is the status of this issue:

    1. There are several bugs against GCC regarding init-list rules. Most of them have gone completely unacknowledged by the GCC team. This at least implies that G++ does have bugs here because the issues have not been closed as invalid
    2. I have received unofficial word from the MSVC compiler team that this is in fact a bug in their compiler and they are working internally to fix it. However, I have no external bug to point to. As of MSVC 2015 Update 3, the old behavior remains.
    3. Clang, which at this point is by far the most pedantic standards-complaint compiler, implements it the way the standard seems to read.

    My personal investigation, discussions with C++ experts at conferences, and unofficial answers I've received from compiler developers indicates that this is a bug in MSVC and GCC, but I'm always reluctant to answer my own questions on StackOverflow. But here we are.

    0 讨论(0)
  • 2020-12-10 02:18

    This note is not related to evaluation order. As it was stated in one of comments, it's about order of converting actual parameters to rvalues and standard does not define such order. You should receive following warning (gcc):

    17:58: warning: operation on 'i' may be undefined [-Wsequence-point]
    

    I modified a program slightly to demonstrate how evaluation of arguments work with {} and ().

    With such modification, program does not depend on order of converting lvalue to rvalue, thus does not have ambiguity which disappointed you.

    #include <iostream>
    
    struct MyType {
      MyType(int i, int j)
        : sum(i + j)
      {
    
      }
    
      int sum;
    };
    
    int main()
    {
      int i = 0;
      int a,b;
      std::cout << MyType{ (a = ++i), (b = ++i) }.sum << '\n';
      std::cout << "Here clauses are evaluated in order they appear: a=" << a << ", b=" << b << std::endl;
      i = 0;
      std::cout << MyType( (a = ++i), (b = ++i) ).sum << '\n';
      std::cout << "Here order of evaluation depends on implementation: a=" << a << ", b=" << b << std::endl;
    }
    

    And the output of this program for clang and gcc:

    clang:

    3
    Here clauses are evaluated in order they appear: a=1, b=2
    3
    Here order of evaluation depends on implementation: a=1, b=2
    

    gcc:

    3
    Here clauses are evaluated in order they appear: a=1, b=2
    3
    Here order of evaluation depends on implementation: a=2, b=1
    

    As you can see, in case of curly brackets, clauses are evaluated in order of appearance under both compilers, which corresponds to the note you provided.

    0 讨论(0)
提交回复
热议问题