Microsoft MVP성태의 닷넷 이야기
VC++: 18. VC++ 7.0에서부터 ? : 연산자 처리가 바뀌었습니다. [링크 복사], [링크+제목 복사],
조회: 21795
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

VC++ 6.0에서는 다음 소스를 컴파일하는 데 오류가 없다면서... 어떤 분이 질문을 하셨습니다.

  #include <fstream>
  #include <iostream>

  template <typename IN, typename OUT>
  void Process(IN &in, OUT &out)
  {
      out << in.rdbuf();
  }

  int main(int argc, char *argv[])
  {
   using namespace std;

   fstream in, out;
   if(argc > 1) in.open(argv[1], ios::in | ios::binary);
   if(argc > 2) out.open(argv[2], ios::out | ios::binary);

   // 에러나는곳
   Process( in.is_open()? in : cin, out.is_open()? out : cout );

   return 0;
  }

하지만, VC++ 7.0에서는 다음과 같은 오류가 난다고.
--------------------------------------------------------------------------
  VC6과 Dev C++에서는 컴파일 됩니다.
  그런데 VC.NET 2003에서는 컴파일러 에러가 나네요

  e:\Temp Projects\DevCpp\main.cpp(29) : error C2446: ':' : 'std::istream'에서
  'std::fstream'(으)로 변환되지 않았습니다.
          소스 형식을 가져올 수 있는 생성자가 없거나 생성자 오버로드 확인이
  모호합니다.
  e:\Temp Projects\DevCpp\main.cpp(30) : error C2446: ':' : 'std::ostream'에서
  'std::fstream'(으)로 변환되지 않았습니다.
          소스 형식을 가져올 수 있는 생성자가 없거나 생성자 오버로드 확인이
  모호합니다.

  표준에 의하면 에러가 나지 않는것이 정상입니다.
  왜 이러지요? VC.NET으로 버전업 되면서 표준을 더 안지키게 됐나여?
--------------------------------------------------------------------------


어찌 보면, template 관련한 소스라서 VC++ 7.0이 표준을 지키지 않는 것처럼 보입니다. (엄밀히, 컴파일이 안된다는 사실은 표준에서 벗어났다고 말할 수 있습니다.)

개인적으로, 표준 스펙 같은 것에는 그다지 관심이 없기 때문에 "표준"에 비춰서 그러한 문제를 분석하는 것은 별로 하고 싶지 않습니다. 단지, 재미있는 문제였고 질문하신 분이 제공한 소스도 간단해서 직접 실행해 보면서 하나 하나 따져 보았습니다. 그러고 나서, 다음과 같은 답변을 했습니다.

--------------------------------------------------------------------------
참...아쉽게 되었네요. ^^; 정말 동작이 안되는군요.

저는 "표준" 같은 것과는 거리가 먼 사람이라서 정확한 스펙에 의한 "멋있는" 설명을 드리기가 좀 그렇지만.

일단, 그 부분은 STL 같은 것에 대한 세부 문법을 지원하지 않는 것과는 거리가 먼 것 같습니다.
어찌된 일인지 모르지만, 표준에 벗어난 것이, ( ? : ) 연산자가 된 것 같습니다.

 ? : 에서 두 번째와 세 번째 operand가 서로 형변환이 가능한 유형이어야 된다는 것이죠.
예를 들어 아래와 같이 오류를 재현할 수가 있습니다.


 int j = 0;
 double tet = 32.35;

 void *pT = ( j != 5 ) ? &j : &tet;


&j와 &tet가 서로간에 형변환이 불가능하기 때문에, 역시나 오류가 나게 됩니다.
이런 경우 다음과 같이 강제 형변환을 하게 되면 정상적으로 동작되는 것을 확인할 수 있습니다.

 void *pT = ( j != 5 ) ? &j : (int *)&tet;

따라서, 제시하신 그 부분에 대한 것도

 Process( in.is_open()? (istream &)in : cin, out.is_open()? (ostream &)out : cout );

위와 같이 필요한 부분에 대해서 형변환을 시켜주면 해결되게 되는 것이죠.

왜 ( ? : ) 연산자가 오퍼랜드에 대해서 상호 형변환을 강제하도록 되었는지는 ... 외부에 있는 저로서는 말씀드릴 수가 없겠네요. ^^
단지, 다소 좀 더 엄격한 "형식안정성"을 제공하려고 그 부분을 그렇게 수정하지 않았나 예상만 해봅니다.

구체적인 것은, ^^; "레드몬드" 사람들에게 물어봐야 겠습니다.
--------------------------------------------------------------------------

 .NET을 공부하면서 느낀 것이지만, 코드에서의 "형식안정성"은 상당히 중요한 부분으로 Microsoft에서 인식하고 있는 것 같습니다. 비록, ? : 연산자에 제공된 자유로움을 빼앗더라도 연산자간의 형식을 맞추도록 강요하는 것이 더 옳다고 판단했던 것 같습니다.

 참고로, VS.NET 2005에서는 기존 C++ Runtime Library 중에서 버퍼 크기가 지정되지 않은 모든 함수를 deprecated로 지정해서 사용을 안하도록 유도하고 있습니다. 그보다는 버퍼크기를 명시하는 새로운 함수를 쓰도록 하고 있는데요. (외국의 어떤 사람은,,, 도대체 Microsoft가 어떻게 표준 Runtime Library 함수를 "deprecated"라고 지정할 수 있는가? 라고 하신 분도 있었는데요.)

 개인적으로, C++ Runtime Library와 ? : 연산자의 그러한 변화를 "표준"이란 테두리와 상관없이 긍정적으로 바라보고 있습니다. (현재는 표준이 아니지만... 다른 컴파일러들도 그런 부분을 따라서 오히려 그것이 새롭게 "표준"으로 지정되어야 하지 않을까요?)








[최초 등록일: ]
[최종 수정일: 6/27/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 196  197  198  [199]  200  201 
NoWriterDateCnt.TitleFile(s)
56정성태10/3/200423736.NET Framework: 10. [.NET 리모팅] 원격개체를 호출한 클라이언트의 연결이 유효한지 판단하는 방법.
55정성태10/3/200424456COM 개체 관련: 11. 내가 생각해 보는 COM의 현재 위치
54정성태8/30/200430149VC++: 10. 내가 생각해 보는 MFC OCX와 ATL DLL에 선택 기준
53정성태11/20/200529279VC++: 9. CFtpFileFind/FtpFileFind가 일부 Unix FTP 서버에서 목록을 제대로 못 가져오는 문제
184정성태11/23/200522957    답변글 VC++: 9.1. FTP 관련 토픽파일 다운로드1
51정성태6/24/200428220VC++: 8. BSTR 메모리 할당 및 해제(MSDN Library 발췌) [1]
50정성태6/16/200421373기타: 6. 1차 데스크톱 컴퓨터 사양
49정성태6/16/200421713기타: 5. 53만 원대 Second PC 마련. ^^
48정성태3/2/200423693.NET Framework: 9. 윈도우즈 발전사를 모아 둔 사이트. [1]
47정성태11/14/200522008VS.NET IDE: 7. 한글 OS에서 Internet Explorer 6.0 with SP1의 UI 언어 바꾸는 방법
45정성태1/26/200421478기타: 4. MCAD 시험
44정성태1/26/200422285VS.NET IDE: 6. 터미널 서비스 포트 변경 ( 서버 및 클라이언트 )
46정성태1/26/200427389    답변글 VS.NET IDE: 6.1. Windows 2003 터미널 서비스 라이센스 서버 없이 접속
114정성태11/14/200518470    답변글 VS.NET IDE: 6.2. [터미널 서버 라이센스] : 활성화 시 오류
43정성태12/23/200322082기타: 3. XP/2003 개인 방화벽 설정파일 다운로드1
40정성태7/23/200325786COM 개체 관련: 10. IE BHO 개체를 개발할 때, 인터넷 익스플로러가 아닌 탐색기에서 활성화 되는 문제 해결 [1]
41김성현7/24/200324480    답변글 COM 개체 관련: 10.1. [답변]: IE BHO 개체를 개발할 때, 인터넷 익스플로러가 아닌 탐색기에서 활성화 되는 문제 해결
42정성태7/29/200322119        답변글 COM 개체 관련: 10.2. feedback 을 받기 위해서 답변 기능을 가능하게 해두었습니다.
39정성태7/17/200328063VS.NET IDE: 5. 원격 제어 3가지 방법
38정성태7/17/200324302.NET Framework: 8. IIS 서버 재설치와 ASP.NET 서비스의 문제점
36정성태7/17/200325191.NET Framework: 7. 시행착오 - WebService 참조 추가 오류
35정성태7/17/200325745.NET Framework: 6. Win2000에서의 .NET COM+ 자동 등록 오류 발생 해결
34정성태7/17/200324331VS.NET IDE: 4. VC++ 원격 디버깅파일 다운로드1
33정성태7/17/200324738VS.NET IDE: 3. Win2000 NAT 서비스
32정성태7/17/200325971COM 개체 관련: 9. _bstr_t, CComBSTR, string 클래스 사용 [1]
31정성태7/17/200322891COM 개체 관련: 8. IDL 구문에서 구조체를 pack 하는 방법
... 196  197  198  [199]  200  201