Implicit conversion failure from initializer list

后端 未结 2 1667
再見小時候
再見小時候 2020-12-13 08:54

Consider the snippet:

#include 

void foo(const std::unordered_map &) {}

int main()
{
        foo({});
}
         


        
2条回答
  •  独厮守ぢ
    2020-12-13 09:32

    List-initialization for references is defined as follows, [dcl.init.list]/3:

    Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is copy-list-initialized or direct-list-initialized, depending on the kind of initialization for the reference, and the reference is bound to that temporary.

    So your code fails because

    std::unordered_map m = {};
    

    fails. List-initialization for this case is covered through this bullet from [dcl.init.list]/3:

    Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

    So the object's default constructor will be called1.
    Now to the crucial bits: In C++11, unordered_map had this default constructor2:

    explicit unordered_map(size_type n = /* some value */ ,
                           const hasher& hf = hasher(),
                           const key_equal& eql = key_equal(),
                           const allocator_type& a = allocator_type());
    

    Clearly, calling this explicit constructor through copy-list-initialization is ill-formed, [over.match.list]:

    In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

    Since C++14 unordered_map declares a default constructor that is non-explicit:

    unordered_map();
    

    So a C++14 standard library implementation should compile this without problems. Presumably libc++ is already updated, but libstdc++ is lagging behind.


    1) [dcl.init]/7:

    To value-initialize an object of type T means:
    — if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called […];

    2) [class.ctor]/4:

    A default constructor for a class X is a constructor of class X that can be called without an argument.

提交回复
热议问题