Issue 152081
Summary Overload resolution incorrectly considers std::initializer_list with narrowing conversions
Labels new issue
Assignees
Reporter Normal-pcer
    ### Description:
When passing `{1, 2.0}` to overloaded functions, compilers select the `std::initializer_list<int>` overload and report a narrowing error. According to the standard, this overload should be excluded from consideration because not all elements can be implicitly converted to X due to narrowing.

### Expected behavior:
The conversion to `std::initializer_list<int>` should be considered invalid during overload resolution per §12.2.4.2.6/5. The overload `f(A)` should be selected as the only viable candidate.

### Actual behavior:
Clang 20.1.0 selects the `initializer_list` overload and emits:  
```
note: insert an explicit cast to silence this issue
error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
```

### Minimal Reproduction (Godbolt):
https://godbolt.org/z/fhrM5MYsq  
```cpp
#include <initializer_list>

struct A { int x; double y; };
void f(A) {}                   // #1
void f(std::initializer_list<int>) {} // #2

int main() {
    f({1, 2.0}); // Should select #1 but selects #2 with error
}
```

### Standard Reference (§12.2.4.2.6/5):
"Otherwise, if the parameter type is std​::​initializer_list<X> and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X..."

### Analysis:
1. The conversion `double(2.0) → int` requires narrowing
2. Therefore, the condition "all elements can be implicitly converted to X" fails
3. The `initializer_list<int>` overload should be excluded during overload resolution

### Affected Standards:
C++11 through C++23 (all show same behavior)

### Request:
Adjust overload resolution to properly exclude candidates where narrowing conversions prevent satisfying the "all elements implicitly convertible" requirement in [over.ics.list]p5.

### Contrast with Explicit Conversion Behavior (Expected Model):
When replacing narrowing with explicit conversion - which should be excluded similarly - compilers correctly reject the candidate during overload resolution:

```cpp
#include <initializer_list>

struct Number {
    explicit operator int() const { return 0; } // 显式转换
};

struct A { int x; Number y; };
void f(A) {}                   // #1
void f(std::initializer_list<int>) {} // #2

int main() {
    f({1, Number{}}); // Correctly selects #1 in all compilers
}
```

This proves:
1. Compilers properly exclude `initializer_list` candidates when conversions are invalid (explicit)
2. Narrowing conversions should follow the same exclusion principle

_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to