Overload resolution for implicit conversion operators used in aggregate Initialization

Consider the following setup:

struct MyInt {
    template<class T>
    operator T() = delete;

    operator int(){ return 42; }
};

struct TestCArr {
    int arr[2];
};

struct TestStdArr {
    std::array<int, 2> arr;
};

MyInt here is implicitly convertible to int, but all other conversions are deleted.

The following compiles as expected with all major compilers using aggreagate initialization to initialize arr[0] with MyInt{} via operator int():

TestCArr{ MyInt{} };

But what is the expected behavior of the following statement?

TestStdArr{ MyInt{} };

To my understanding, this should not compile:
MyInt has a conversion operator to std::array<int, 2>, so that should be the best fit. But that operator is deleted, so I’d expect a compile time error. (The difference to before is that it is impossible to have a conversion operator to int[2], so the conversion to int is used.)

MSVC and gcc seem to agree with me, but clang compiles the statement, picking the conversion operator to int and aggregate initializes the first member of arr (see https://godbolt.org/z/dK4ronrGv).

So is my understanding correct that operator std::array<int, 2>() is a better fit than operator int() and therefore has a higher priority, even though it is deleted?

P.S. If I remove the deleted operator T() from MyInt, the above statement compiles with all three major compilers, all choosing operator int() to perform aggregate initialization: https://godbolt.org/z/sYr7ff793

P.P.S If I use the following definition of MyInt, the behavior of all compilers stays the same (removing arguments concerning templates vs non-templates and more constrained vs less constrained): https://godbolt.org/z/cvhMj9xPq

struct MyInt {
    template<class T>
      requires (!std::integral<T>)
    operator T() = delete;


    template<class T>
      requires std::integral<T>
    operator T() { return 42; };
};

1

I think clang is wrong here.

List initialization supports brace elision. There a mechanism by which you figure out if an initializer refers to the current element or a sub-element of that element. That rule is [dcl.init.aggr]/14:

Each initializer-clause in a brace-enclosed initializer-list is said to appertain to an element of the aggregate being initialized or to an element of one of its subaggregates. Considering the sequence of initializer-clauses, and the sequence of aggregate elements initially formed as the sequence of elements of the aggregate being initialized and potentially modified as described below, each initializer-clause appertains to the corresponding aggregate element if

  1. the aggregate element is not an aggregate, or
  2. the initializer-clause begins with a left brace, or
  3. the initializer-clause is an expression and an implicit conversion sequence can be formed that converts the expression to the type of the aggregate element, or
  4. the aggregate element is an aggregate that itself has no aggregate elements.
    Otherwise, the aggregate element is an aggregate and that subaggregate is replaced in the list of aggregate elements by the sequence of its own aggregate elements, and the appertainment analysis resumes with the first such element and the same initializer-clause.

So when you do TestCArr{ MyInt{} } for instance, we first try to see if MyInt{} appertains to int arr[2]. And it doesn’t. (1) this is an aggregate, (2) our initializer-clause does not begin with a left brace, (3) the initializer-clause is an expression but we cannot form a conversion sequence to int[2], and (4) int[2] isn’t empty. So we recurse and consider the first element of the int[2], which gets initialized.

But when you do TestStdArr{ MyInt{} }, the logic isn’t quite the same. In (3), we can form an implicit conversion sequence to std::array<int, 2>. That conversion function is deleted, but that still counts as an implicit conversion sequence (which is important because otherwise deleted wouldn’t really work the way as intended…). So we don’t recurse into the sub-aggregates of std::array<int, 2>, instead directly initializing the std::array. Which should fail.

gcc and msvc get this right.

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật