how to avoid undefined execution order for the constructors when using std::make_tuple

前端 未结 5 1501
攒了一身酷
攒了一身酷 2020-12-01 12:33

How can I use std::make_tuple if the execution order of the constructors is important?

For example I guess the execution order of the constructor of class A and the

5条回答
  •  旧时难觅i
    2020-12-01 13:08

    The trivial solution is not to use std::make_tuple(...) in the first place but to construct a std::tuple<...> directly: The order in which constructors for the members are called is well defined:

    template 
    std::istream& dummy(std::istream& in) {
        return in;
    }
    template 
    std::tuple parse(std::istream& in) {
        return std::tuple(dummy(in)...);
    }
    

    The function template dummy() is only used to have something to expand on. The order is imposed by construction order of the elements in the std::tuple:

    template 
        template 
        std::tuple::tuple(U...&& arg)
            : members_(std::forward(arg)...) { // NOTE: pseudo code - the real code is
        }                                        //       somewhat more complex
    

    Following the discussion below and Xeo's comment it seems that a better alternative is to use

    template 
    std::tuple parse(std::istream& in) {
        return std::tuple{ T(in)... };
    }
    

    The use of brace initialization works because the order of evaluation of the arguments in a brace initializer list is the order in which they appear. The semantics of T{...} are described in 12.6.1 [class.explicit.init] paragraph 2 stating that it follows the rules of list initialization semantics (note: this has nothing to do with std::initializer_list which only works with homogenous types). The ordering constraint is in 8.5.4 [dcl.init.list] paragraph 4.

提交回复
热议问题