Why do auto and template type deduction differ for braced initializers?

前端 未结 3 2071
伪装坚强ぢ
伪装坚强ぢ 2020-11-29 09:23

I understand that, given a braced initializer, auto will deduce a type of std::initializer_list, while template type deduction will fail:



        
3条回答
  •  借酒劲吻你
    2020-11-29 10:05

    The reason is described in N2640:

    A {}-list cannot deduce against a plain type parameter T. For example:

    template void count(T); // (1).
    struct Dimensions { Dimensions(int, int); };
    size_t count(Dimensions); // (2).
    size_t n = count({1, 2}); // Calls (2); deduction doesn't
                              // succeed for (1).
    

    Another example:

    template
    void inc(T, int); // (1)
    template
    void inc(std::initializer_list, long); // (2)
    inc({1, 2, 3}, 3); // Calls (2). (If deduction had succeeded
                       // for (1), (1) would have been called — a
                       // surprise.)
    

    On the other hand, being able to deduce an initializer_list for T is attractive to allow:

    auto x = { 1, 1, 2, 3, 5 };
    f(x);
    g(x);
    

    which was deemed desirable behavior since the very beginning of the EWG discussions about initializer lists.

    Rather than coming up with a clever deduction rule for a parameter type T matched with a {}-list (an option we pursued in earlier sketches and drafts of this paper), we now prefer to handle this with a special case for "auto" variable deduction when the initializer is a {}-list. I.e., for the specific case of a variable declared with an "auto" type specifier and a {}-list initializer, the "auto" is deduced as for a function f(initializer_list) instead of as for a function f(T).

    For conclusion, the problem is that if we allow a {}-list to deduce against a plain type parameter T, then the function with parameter T would have very high priority during overload resolution, which may cause wired behavior (like the examples above).

提交回复
热议问题