8

vector<T>는 벡터의 크기를 사용하는 생성자를 가지고 있으며, 내가 아는 한 그것은 내가 할 수없는int에서 vector 로의 암시 적 변환?

void f(std::vector<int> v); 
int main() 
{ 
    f(5); 
} 

을 컴파일하려면 다음 코드가 실패한다는 사실에 의해 입증 할 수 명시 적입니다 이해하고 설명을 요구하고있는 다음 코드는

std::vector<std::vector<int>> graph(5, 5); 

뿐만 아니라 그것은 컴파일 않으며, 실제로 것이다 5 그래프의 크기를 조정하고 오 제로의 벡터에 각 요소를 설정, 즉 동일한을 수행하는 컴파일 이유 코드는 보통 다음과 같습니다 :

std::vector<std::vector<int>> graph(5, std::vector<int>(5)); 

어떻게? 왜?

컴파일러 : MSVC10.0


확인, 그것이 MSVC 버그 (또 다른 하나) 것 같다. 누군가가 (즉,이 재생되는 경우를 요약) 응답의 버그에 정교한 수 있다면 나는 기꺼이 그것을

+4

이것은 (올바르게) GCC 4.7에서는 컴파일되지 않습니다. 또 다른 MSVC++ 표준 외의 이상 함. 그들은 아마도 생성자'explicit'을 표시하는 것을 잊어 버렸을 것입니다, 당신은''을 파헤쳐 그것을 검사 할 수 있습니다. – syam

+0

@syam : 열에 기쁘다. GCC에서 컴파일하는 데 실패하지만 실제로 이상한 점은 첫 번째 예가 MSCV에서 컴파일되는 반면 다른 예에서는 MSCV가 컴파일되지 않는다는 점이다. 그게 정말 이상한거야 –

+0

@ArmenTsirunyan VS2012에서 컴파일하지 마십시오; 오류 메시지는 생성자가 '명시 적'임을 나타냅니다. – Praetorian

답변

7

사실 버그는 아닙니다. 첫 번째 코드가 컴파일되지 않는 동안 코드의 두 번째 부분을 허용하기 위해 잘못 될 수있는 것이 문제입니다.

std::vector<std::vector<int>> graph(5, 5); 

는 컴파일러 분명하지 않다 :

문제는 당신이 당신이 할 때 전화를 원하는 생성자 당신에게 분명한 것 같다 동안이다. 그이 될 것입니다, 그래서 두 번째는 완벽하게 일치되는 동안

vector(size_type,const T& value = T()); 

template <typename InputIterator> 
vector(InputIterator first, InputIterator last); 

가 첫 번째는, size_type-5의 변환 (부호 인)이 필요합니다 특히 잠재적 인수를 사용할 수있는 두 개의 생성자 오버로드가있다 하나는 컴파일러에 의해 픽업 ...

...하지만 컴파일러는 필요로하는 두 번째 오버로드의 추론 유형 InputIterator은로 전화 인 것처럼 중요한 동작합니다 인 경우 :

vector(static_cast<size_type>(first),static_cast<T>(last)) 

무엇 C++ 03 표준을 효과적으로 의무화하는 것은 2 번째의 인수가 명시 적으로 때문이다 원래 유형 int에서 대상 유형 std::vector<int>으로 변환되었습니다. 변환이 명백하기 때문에 오류가 발생합니다.

C++ 11 표준은 인수가 실제로 입력 반복자가 아닌 경우 반복기 생성자를 사용하지 않도록 SFINAE를 사용하도록 변경하므로 C++ 11 컴파일러에서 코드가 거부되어야합니다 (이는 아마도 이유 일 것입니다 몇몇은 이것을 버그라고 주장했다.)

-4

표준 : : 벡터를 < INT를 받아 들일> 말하자면 size_type 및 & INT CONST를 받아들이는 생성자가 있습니다. 이 경우 호출 될 것으로 예상되는 생성자입니다. 벡터가 5로 초기화되고 값이 5 인 정수가됩니다.

+3

분명히 내 질문에 읽을 수 있으므로 않습니다. * –

+0

@ArmenTsirunyan 컴파일러 버그. – selalerer

+0

당신의 대답이 말이 안되는 경우 –

1

이것은 실제로 확장이 아닌 버그입니다.

호출되는 생성자는 두 개의 반복자를 사용하는 생성자입니다 (실제로 서명은 동일한 유형의 두 매개 변수와 일치합니다). 두 개의 반복자가 실제로 int 일 때의 구체화를 호출합니다. end의 값을 사용하여 value_type을 명시 적으로 구성하고 벡터에 begin 복사본을 채 웁니다. 그것은이 생성자를 호출하는 것처럼

+0

나는 이해할 것이라고 생각하지 않는다 ... int는 반복자로서 무엇을 의미 하는가? –

+0

@ArmenTsirunyan :'std :: vector'는 begin과 end 반복자를 취하는 생성자를 가지고 있습니다. 그것은 당신의 호출과 일치하는'template vector (_It first, _It last)'와 같이 정의됩니다.그런 다음 '_It'이 'int'인 경우를 처리하는 오버로드 중 하나 인 '_It'의 유형에 따라 다양한 오버로드가있는 함수를 호출합니다. –

+0

질문에 대답하기 위해 iterator는 __not__이지만 코드는 int를 제공하는 경우를 처리합니다. –

2

는 나에게 그것은 본다 :

template <class InputIterator> 
vector (InputIterator first, InputIterator last, 
    const allocator_type& alloc = allocator_type()); 

잘 모르겠어요 생성자가 여러 매개 변수를 사용하기 때문에 explicit는, 그것으로 오는 곳. int에서 벡터로 자동 변환하지 않습니다.

+0

표준은 다른 생성자도 가능한 일치가 될 때 명시 적으로 2 반복기 생성자 사용을 금지합니다. –

+0

내가 이해할 것 같지 않은데 ... int는 입력 반복자가 무엇입니까? –

+0

'InputIterator'는 템플릿 매개 변수 일뿐입니다. 모든 유형이 될 수 있습니다. –