Visual Studio에서 다음 코드를 테스트하여 "A (double)"를 컴파일하고 인쇄합니다.
#include <iostream>
#include <initializer_list>
struct A {
A(std::initializer_list<int>) { puts("initializer_list<int>"); } // (1)
A(std::initializer_list<float>) { puts("initializer_list<float>"); } // (2)
A(double) { puts("A(double)"); } // (3)
};
int main() {
A var{ 1.1 };
}
그러나 IntelliSense와 http://ideone.com/ZS1Mcm 은 둘 이상의 생성자 "A :: A"인스턴스가 인수 목록과 일치한다고 말하면서 동의하지 않습니다 (이니셜 라이저 목록 생성자 모두를 의미 함). (1) 또는 (2)가 제거되면 " 'double'에서 'float'로 변환하려면 축소 변환이 필요하므로"코드가 더 이상 컴파일되지 않습니다.
이것은 버그입니까? 동작이 일관되지 않은 것처럼 느껴지지만 VS13과 VS15에서 동일한 동작이 표시되므로 더 많은 것이있을 수 있습니까?
코드 형식이 잘못되었습니다. §8.5.4 / (3.6) 적용 :
그렇지
T
않고 클래스 유형이면 생성자가 고려됩니다. 적용 가능한 생성자가 열거되고 오버로드 해결 (13.3, 13.3.1.7)을 통해 최상의 생성자가 선택됩니다.
이제 §13.3.3.1.5가
인수가 이니셜 라이저 목록 (8.5.4)이면 표현식이 아니며 매개 변수 유형으로 변환하는 데 특별한 규칙이 적용됩니다. [...] 파라미터 유형 인 경우
std::initializer_list<X>
상기 초기화리스트의 모든 요소가 암묵적으로 변환 할 수X
, 암시 적 변환 시퀀스가리스트의 요소를 변환해야 최악 변환 되나X
, 또는 초기화리스트에 요소가없는 경우 신원 변환.
변환 1.1
타입 인 double
(!)로하면 int
에서 전환하면서, 전환 순위 부동 적분 변환이다 1.1
행은 float
또한 전환 순위를 갖는 - 부동 소수점 변환이다.
따라서 두 변환 모두 똑같이 좋으며 §13.3.3.2 / (3.1)도 둘 중 하나를 구분할 수 없기 때문에 호출이 모호합니다. 축소는 과부하 해결이 완료 될 때까지 역할을하지 않으므로 후보 세트 또는 선택 프로세스에 영향을 미치지 않습니다. 보다 정확하게는 후보자는 13.3.2 / 3에 설정된 요구 사항을 충족해야합니다.
둘째,
F
실행 가능한 함수가 되려면 각 인수에 대해 해당 인수를의 해당 매개 변수로 변환 하는 암시 적 변환 시퀀스 (13.3.3.1)가 있어야합니다F
.
제 인용에 도시 된 바와 같이, 그러나, 변환 암시 적 변환 시퀀스 것을 {1.1}
행은 std::initializer_list<int>
행 최악 변환 되나 1.1
에 int
유효한 (기존!)이 하나 - 부동 적분 변환이다.
{1.1f}
또는 변경 initializer_list<float>
에를 <double>
변환으로, 코드가 잘 형성된다 1.1f
하려면 float
신원 변환입니다. 표준은 (3.6)에 해당 예를 제공합니다.
[ 예 :
struct S { S(std::initializer_list<double>); // #1 S(std::initializer_list<int>); // #2 }; S s1 = { 1.0, 2.0, 3.0 }; // invoke #1
— 최종 예 ]
더 흥미롭게도
struct S {
S(std::initializer_list<double>); // #1
S(std::initializer_list<int>); // #2
};
S s1 = { 1.f }; // invoke #1
또한 유효 -에서 변환하기 때문1.f
에이double
부동 소수점 인 홍보 변환 순위보다 더 승진 순위를 갖는.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다