Why is the std::initializer_list constructor preferred when using a braced initializer list?

前端 未结 3 1733
借酒劲吻你
借酒劲吻你 2020-12-01 07:50

Consider the code

#include 

class Foo
{
    int val_;
public:
    Foo(std::initializer_list il)
    {
        std::cout <<          


        
3条回答
  •  独厮守ぢ
    2020-12-01 08:16

    The n2100 proposal for initializer lists goes into great detail about the decision to make sequence constructors (what they call constructors that take std::initializer_lists) to have priority over regular constructors. See Appendix B for a detailed discussion. It's succinctly summarized in the conclusion:

    11.4 Conclusion

    So, how do we decide between the remaining two alternatives (“ambiguity” and “sequence constructors take priority over ordinary constructors)? Our proposal gives sequence constructors priority because

    • Looking for ambiguities among all the constructors leads to too many “false positives”; that is, clashes between apparently unrelated constructors. See examples below.
    • Disambiguation is itself error-prone (as well as verbose). See examples in §11.3.
    • Using exactly the same syntax for every number of elements of a homogeneous list is important – disambiguation should be done for ordinary constructors (that do not have a regular pattern of arguments). See examples in §11.3. The simplest example of a false positive is the default constructor:

    The simplest example of a false positive is the default constructor:

    vector v; 
    vector v { }; // potentially ambiguous
    void f(vector&); 
    // ...
    f({ }); // potentially ambiguous
    

    It is possible to think of classes where initialization with no members is semantically distinct from default initialization, but we wouldn’t complicate the language to provide better support for those cases than for the more common case where they are semantically the same.

    Giving priority to sequence constructors breaks argument checking into more comprehensible chunks and gives better locality.

    void f(const vector&);
    // ...
    struct X { X(int); /* ... */ };
    void f(X);
    // ...
    f(1);     // call f(X); vector’s constructor is explicit
    f({1});   // potentially ambiguous: X or vector?
    f({1,2}); // potentially ambiguous: 1 or 2 elements of vector
    

    Here, giving priority to sequence constructors eliminates the interference from X. Picking X for f(1) is a variant of the problem with explicit shown in §3.3.

提交回复
热议问题