2010-01-05 9 views
7

다음 코드를 고려 반복자 :C++ 명시 적으로 생성자와

해야 위의 컴파일을? 제 느낌은 생성자가 explicit으로 표시되어서는 안된다는 것입니다. 명확한 오류 메시지를 제공 동의 ++

의 Microsoft Visual C : Comeau's online compiler를 사용하지만 cannot convert from 'int' to 'const A'; Constructor for struct 'A' is declared 'explicit'

는 코드가 성공적으로 컴파일합니다.

올바른 내용은 무엇입니까?

편집 : (A operator <에 추가 한 후) set-vector 변경 흥미롭게

는 에러를 수득 모두 컴파일러시킨다.

그러나 vector<int>map<int, int>vector<A>에서 map<A, A>으로 변경하면 두 컴파일러 모두 코드를 허용하게됩니다.

+0

간접적으로 여기에 답하십시오 : http://stackoverflow.com/questions/1943228/implicit-constructor-conversion-works-on-explicit-vectorvector-only-sometimes –

+1

방금 ​​그 질문 + 답을 바탕으로 대답을 작성했습니다. 'std :: vector :: iterator'는 정수형이 아니기 때문에 fill-constructor가 호출되지 않기 때문에 실제로 적용되지 않습니다. 그래서 나는 그것을 삭제했다. 모든 컨테이너 생성자에서 표준은 * 명시 적 변환을 금지하지 않는다고 말할 수 있습니다. – Potatoswatter

+0

VS 2010 Beta는 Comeau 및 gcc로 작동합니다. –

답변

3

GCC의 STL 구현을 살펴본 결과 비슷한 동작을 보입니다. 이유가 여기 있습니다.vector

  • 요소는 두 종류의 XV를 받아 vV이다 (나는 약간 의역있어) new(p) X(v)를 호출하는 일반적인 함수 템플릿에 의해 초기화됩니다. 이렇게하면 명시 적 변환이 가능합니다. set 또는 map
  • 요소는 구체적 T const &가 전달되기를 기대 _tree<T,…>의 프라이빗 멤버 함수에 의해 초기화된다.이 멤버 함수 (템플릿의 구성원 인 이상) 템플릿 아닌 초기 그렇다면 값을 암시 적으로 T으로 변환 할 수 없으면 호출이 실패합니다. (다시 코드를 단순화합니다.)

표준은 범위가있는 컨테이너를 초기화 할 때 명시 적 변환 작업이 필요하지 않거나 암시 적 변환이 작동하지 않아도됩니다. 범위가 컨테이너에 복사된다고 간단히 말합니다. 당신의 목적을 확실히 모호하게합니다.

몇 주전에 the one I had과 같은 문제를 고려하여 이미 표준을 어떻게 수정했는지 모른 채 그런 모호함이 있습니다.

1

나는 std::vector<A> As(Iterator,Iterator)이 STL의 특정 구현에서 어떻게 구현되는지에 달려 있다고 생각합니다.

+0

표준 라이브러리의 동작은 구현에 의존하지 않아야합니다. –

+1

다음으로, 표준이 두 가지가 아닌 동일한 방식으로 해석 될 수있는 장소 (매우 드문 경우)가 있습니다. –

0

이 코드는 꼬모에서 컴파일되지 않습니다 :

class Foo 
{ 
public: 
explicit Foo(int bar) 
{ 
} 
}; 

class Bar 
{ 
void DoStuff(Foo foo){ 

} 
void DoStuff2() 
{ 
    DoStuff(4); 
} 
}; 

오류 메시지 :

"ComeauTest.c", line 16: error: no suitable constructor exists to convert from "int" 
      to "Foo" 
    DoStuff(4); 
      ^

1 error detected in the compilation of "ComeauTest.c". 

그래서 초보적인 수준에서 온라인 컴파일러가 명시 적으로 생성자를 지원합니다. 벡터/반복자와 관련이 있어야합니다.

편집이 그러나 컴파일 : 명시 적 변환입니다

Foo foo = (Foo)5; 

을, 즉 OK 그래서. 내 생각에 Comeau 벡터 클래스는 생성자에서 어딘가에 명시 적 캐스트를 수행하지만 Microsoft 라이브러리는 그렇지 않습니다. 명시 적 생성자에

더 - http://www.glenmccl.com/tip_023.htm

0

네, 컴파일해야한다. 생성자가 사용되지 않으면 Explositness는 문제가되지 않습니다.

+0

생성자가 사용되지 않는다면 어떻게 int에서 A로 변환 할 수 있습니까? – user200783

+0

아무것도 만들어지지 않고 아무것도 변환되지 않습니다. 두 벡터가 모두 비어 있습니다. –

+0

"As"로 작성되기 전에 무언가가 "ints"벡터에 삽입되면 동작이 동일합니다. – user200783

1

이것은 다소 까다로운 질문이며 VisualStudio가 맞고 Comeau가 잘못되었다는 것입니다 (믿을 수 없을 것 같습니다).

워드 의해 판독 워드 경우 표준 (인용 참조) 복사 생성자의 관점에서 그 벡터 생성자를 정의하고, 그것이 사실상 반복자 비 참조하여 얻어지는 객체가 제 타입 T로 변환되어야 함을 의미 복사 생성자를 호출해야합니다. 이 시점에서 명시 적 생성자를 사용하면 코드가 컴파일되지 않아야합니다.

한편 구현에서는 역 참조 된 반복자를 인수로 취하는 생성자를 직접 호출해야합니다.이 경우 생성자 호출이 명시 적이며 코드가 컴파일되어야합니다.이것은 복사 생성자이 T 유형의 객체에 대해 단일 상수 참조를 취하는 생성자로 지정된 유형 T에 대해 정의되어 있기 때문에 아래의 인용문에 정확히 어긋납니다.

생각할 수 없습니다. Comeau 접근법을 사용하지 않는 합리적인 주장과 나의 믿음 (이것은 단지 개인적인 견해이다)은 벡터 생성자의 복잡성에 관한 표준의 표현이 을 필요로하는 것으로 재 작성되어야한다고 N은 적절한 T 생성자은 적절한 경우 T(*first) 호출과 일치하는 생성자 (즉, InputIterator::value_type (값 또는 가능한 경우 상수 참조)를 사용하는 생성자이거나 T 복사 const T. ructor에 InputIterator::value_type에서 암시 적 변환 후

23.2.4.1은 [lib.vector.cons]/1

복잡성 : 생성자 템플릿 벡터 (제 Input Iterator와 , Input Iterator와 마지막) 만 N하게 T 의 복사 생성자 (N은 첫 번째와 마지막 사이의 거리 임)에 대한 호출이며 반복자가 처음이고 마지막이 전달, 양방향 또는 임의 액세스 범주 인 경우 다시 할당하지 않습니다. 그것은 을 단지 입력 반복자 인 경우 T 복사 생성자에 대한 호출 N 을 호출하고 로그 N 재 할당을 수행합니다.

나는 VS 컴파일러는 주어진 다르게 동작 할 때 방법을 알고 싶습니다 g으로

struct T1; 
struct T2 { 
    operator T1(); 
}; 
struct T1 { 
    T1(T2 const &) { std::cout << "T1(T2)" << std::endl; } 
}; 
T2::operator T1() { 
    std::cout << "T2::operator T1" << std::endl; 
    return T1(*this); 
} 
int main() { 
    std::vector<T2> v2; 
    v2.push_back(T2()); 
    std::vector<T1> v1(v2.begin(), v2.end()); 
} 

++ 결과가 T2::operator T1가 호출되지 않는 것입니다, 오히려 v1의 요소가의 요소에서 직접 구성된다 v2. 나는 VS에서 컴파일러가 T2::operator T1을 사용하여 v2의 각 요소를 T1 요소로 변환 한 다음 복사 생성자를 호출한다고 가정합니다. 그래?

+0

실제로 VS 컴파일러로 코드를 컴파일하려고하면 'std :: allocator <_Ty> :: construct': 'T2'에서 'const T1'로 매개 변수 2를 변환 할 수 없습니다 ([_Ty = T1 ] 이유 : 'T2'에서 'const T1'로 변환 할 수 없습니다.이 변환을 수행 할 수있는 사용자 정의 변환 연산자를 사용할 수 없거나 연산자를 호출 할 수 없습니다. – user200783

+0

방금 ​​VS2010 베타 테스트를 마쳤으며 컴파일 할뿐만 아니라 실행합니다. 같은 동작으로 g ++ :'T1 (T2 const &)'생성자가 호출됩니다. –

1

이것은 언어 사양 문제가 아니라 STL 라이브러리가 구현되는 방식에 관한 질문입니다. 언어 스펙에는 이것이 작동하는 것을 금지하는 것도 없으며, 작동하도록 요구할만한 것도 없습니다.

할당 연산자를 사용하여 암시 적 변환을 시도하기 위해 stl :: vector 생성자가 작성된 경우 실패합니다. Microsoft STL 구현은 생성자 호출을 통해 초기화하는 동안 반환 값 최적화를 사용하는 경우가 많습니다.이 경우이 코드는 정상적으로 작동합니다.

이 작동하는 유일한 이유는 stl :: vector 생성자가 템플리트 화되고 input_iterator 또는 더 정확하게 입력의 모든 필수 기능을 지원한다는 것만 요구된다는 점입니다 반복자.

또한 크로스 플랫폼 코드를 작성하는 것이 왜 어려운지를 보여주는 좋은 예가 될 수 있습니다. 때때로 컴파일러가 반드시 언어 표준을 벗어나는 문제는 아니지만 코드는 여전히 이식 가능하지 않습니다.

관련 문제