2013-12-09 6 views
1

std::pair<int, int>here의 네 번째 정의를 사용하여 const std::pair<int, float>&에서 내재적으로 생성 가능합니다.왜 std :: pair <int, int> const std :: pair로부터 생성 가능한가? <int, float> &?

#include <iostream> 
#include <vector> 
#include <utility> 

int main() { 
    std::vector<std::pair<int, float>> v = { {1, 1.5f} }; 

    // The interesting line: 
    const std::pair<int, int>& x = v[0]; 

    const auto& y = v[0]; 

    std::cout << "before:\n"; 
    std::cout << "\tv[0]: " << std::get<1>(v[0]) << "\n"; 
    std::cout << "\tx: " << std::get<1>(x) << "\n"; 
    std::cout << "\ty: " << std::get<1>(y) << "\n"; 

    std::get<1>(v[0]) = 3.5f; 

    std::cout << "\nafter:\n"; 
    std::cout << "\tv[0]: " << std::get<1>(v[0]) << "\n"; 
    std::cout << "\tx: " << std::get<1>(x) << "\n"; 
    std::cout << "\ty: " << std::get<1>(y) << "\n"; 
} 

출력은

이 (xy보다 참조 같은 "느낌"고 어색한 것 같다

before: 
    v[0]: 1.5 
    x: 1 
    y: 1.5 

after: 
    v[0]: 3.5 
    x: 1 
    y: 3.5 

(ideone link) 점에서 그것은을 (합법적으로) 참조 무엇인지 아마도 사용자의 관점에서 볼 때 "잘못된"것입니다.)

마크가없는 해당 생성자의 이유는 무엇입니까? 에 explicit? (I 중요한 유스 케이스가 있으리라 믿고있어.)

+0

나는 미래를 주목할 것이다. std :: tuple은 비슷한 생성자를 가지고있다. –

+1

@Dave : '명시 적으로'차이를 만들지 않는 이유는 무엇입니까? 그것은 나에게해야하고, const 참조에 바인딩하기 위해 일시적으로 변환하는 것은 암시 적 변환이라고 생각합니다. 예를 들어 http://ideone.com/k6qd6l –

+0

SteveJessop의 의견에 비추어 볼 때 Dave의 답변에 동의하지 않았습니다. –

답변

3
// The interesting line: 
const std::pair<int, int>& x = v[0]; 

그 코드는 동일합니다 일시적으로 const 참조를 바인딩합니다. const을 제거한 경우 (그리고 VS를 사용하지 않는 경우) 코드가 실패해야합니다.

+0

확실하게, 그것은 내게 일어난 일을 추측했다. 내가 궁금한 점은 생성자가 "왜"존재하는지, 왜 명시 적이 지 않은지이다. –

+1

@JacobParker :이 생성자는 요소 현명한 변환을 제공하기위한 것이며, 두 멤버 모두 요소에 따라 암시 적으로 변환 할 수있는 경우에만 오버로드 확인에 참여해야합니다 (C++ 11에서는 C++ 03에서 표준이 다른 것을 말했지만 구현이 불가능했기 때문에 명시적인 전환이 발생했습니다. 이 아이디어는 요소가 변환 가능하다면 왜 유형을 변환 가능하게 만들지 않는가? 'std :: map () .insert (std :: make_pair (1,2))'는 정확히 동일한 변환을 사용합니다 ['value_type'는'std :: pair < const int, int>'] –

+0

@ david-rodriguez-dribeas 아, std :: map :: 삽입 예제가 좋습니다. 감사. –

3

xv[0]에 대한 참조 아니다, 그것은 x의 수명을 일치 유형 std::pair<int, int>의 개체에 대한 참조입니다. const T&을 초기화하면 직접 참조 할 수없는 경우 새 객체가 오른쪽에서 생성됩니다. 이 경우

, 당신이 쓴 작문과 같은이었을 것입니다 :

const std::pair<int, int> x = v[0]; // note: no reference 

당신은 아마 변환을 int로 인해 부동의,하지만 이것에 대해 경고를 받아야합니다.

const std::pair<int,int>& x = std::pair<int,int>(v[0]); 

당신이 때문에 std::pair<int,int>std::pair<int,float>에서 변환의 존재에 컴파일러가 허용되는 점이다 놀라게 (그리고 필수) 발행을 만들 :

관련 문제