C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[76049] Re:Re:Re: 내공이 엄청나시네요
[] 1412 읽음    2021-02-16 13:15
막힐때마다 구글링해도 자료도 안나오고... 포럼엔 한계가 있고... 저도 그만 접고
C#으로 갈아타는것 진지하게 고민중입니다. ㅠㅠ


우인텍크 님이 쓰신 글 :
: 알수 없는 에라가 나면 Build
: 그래도 안되면 Clean후 Build
: 그래도 안되면 IDE 재시작
: 그래도 안되면 재설치
: 그래도 안되면 추가비용 지불해서 새버전 구매
: 그래도 안되면 또 추가비용 지불
:
: 언제까지 악순환을
:
: 기부천사도 아니고
: 10.4.2 에서도 같은 식이라면 Visual Studio 로
: 완전히 갈아탈 생각입니다
:
:
: 빌더(TWx) 님이 쓰신 글 :
: : 아루스 님이 쓰신 글 :
: : : 테스트 예제:
: : : 14] auto Test{_STD make_unique<TStringList>()};
: : : 15] [](TStrings * Var) {
: : : 16]     Var->Values["Key"] = "Value";
: : : 17] }(Test.get());
: : :
: : : 컴파일 에러:
: : : [bcc64 Error] Unit1.cpp(16): 'this' cannot be implicitly captured in this context
: : :
: : : 위와 같이 lambda expression 내부에서 capture가 필요없는 parameter의 property에 값을 쓸 경우 에러가 발생합니다.
: : : 암묵적 this capture에 대한 에러인데, 이 코드에서 this capture가 발생해야 할 이유를 모르겠습니다.
: : : 
: : : 위와 같은 경우에는 Var->Add("Key=Value"); 로 바꾸면 this capture가 없어도 되긴 합니다만,
: : : property의 값을 바꾸는 함수가 없을 경우 모두 구현해야해서 불편함이 생기네요.
: :
: :
: :
: :
: : 답변:
: :
: :
: : 질문에 언급되어 있는 경우와 같이...
: :
: : 람다에서 outter scope를 참조하고 있지않고, 람다 인수로 넘어온 파라미터만 참조하고 있으므로
: : 정상적으로 구현되어 있는 C++ 컴파일러라면 아무런 에러 없이 컴파일 할 수 있어야 합니다.
: :
: :
: : 그러나...
: :
: : 엠바 툴은 C++ 컴파일러가 엉터리로 구현되어 있어서 에러가 발생하는 겁니다.
: :
: :
: :
: : 엠바툴에서 TStrings 클래스의 Values 프로퍼티는 다음과 같이...
: :
: :
: : 1. 파스칼인 경우...
: :
: : function GetValue(const Name: string): string;
: : procedure SetValue(const Name, Value: string);
: : property Values[const Name: string]: string read GetValue write SetValue;
: : 

: :
: : 2. C++빌더인 경우...
: :
: : UnicodeString __fastcall GetValue(const UnicodeString Name);
: : void __fastcall SetValue(const UnicodeString Name, const UnicodeString Value);
: : __property UnicodeString Values[const UnicodeString Name] = {read=GetValue, write=SetValue};
: : 

: : 으로 정의되어 있는데...
: :
: :
: : OOP 디자인 룰에서 클래스 멤버 변수는 getter()나 setter() 인터페이스 함수를 통해서 액세스 해야 하고
: : 내부 데이타 멤버는 외부로 알려지지 않게 캡슐화 해서 사용하는 게 대원칙이라 C++에선 컴파일러가 property 신텍스를
: : 지원하더라도 쓰는 일이 없죠.
: :
: : 엠바 툴에서 property 를 쓰는 것은 함수를 변수처럼 다룰 수 있는 메카니즘이 없으면 Object Inspector를 이용한
: : Form Design 방식이 불가능 하기 때문 입니다.
: :
: :
: : 컴파일러가...
: :
: : Var->Values["Key"] = "Value";
: :
: : 구문을 만나면 property에 정의되어 있는 패턴대로...
: :
: : 소스코드를... 매크로 확장하듯 
: :
: : Var->SetValue("Key", "Value"); 로 치환해서 컴파일 할 뿐이죠.
: :
: : 디자인 타임시에 property 값을 바꾸는 것은 RTTI를 이용한 꼼수를 이용해서 Object Inspector를 구현해 놓은 것에 불과한 거고.
: :
: :
: :
: : 헐.... 손님이 와서 한가해지면 이어서 쓸게요
: :
: :
: :
: : 명절이라고 손님들이.....
: :
: :
: : 부언으로...
: :
: : 엠바에선 RTTI라는 용어를 대서특필하듯 쓰고 있지만...
: : 엄밀하게 보면 RTTI라기 보다는 Java 컴파일러에서의 Type Info Meta 정보와 같은 개념 입니다.
: :
: : 델파이 컴파일러 내부구조도 그렇고.
: : 앤더스 헤일즈버그가 MS에서 TypeScript ( static type safty 버전의 JavaScript 라고 보면 됌) 언어를 맏고 있는 것을 보면
: : 이 친구가 대학에서 컴파일러 이론을 Java 로 배운 듯.
: :
: : 컴파일러가 세세한 Type Info Meta 정보를 생성하지 않으면 Object Inspector를 이용한 Form Design 방식도 불가능 하고...
: : LiveBinding Design 방식도 불가능 하기 때문에 델파이로 컴파일 된 바이너리는 덩치가 커집니다.
: :
: : C++에서도 RTTI (원래 의미의 RTTI) 가 사용되지만 다음과 같이...
: :
: : typeid(int) == typeid(int&);
: :
: : typeid가 지정되어 있는 구문에 대해서만 컴파일러가 런타임 타입 정보를 생성하므로...
: : 모든 타입에 대해서 Type Info Meta 정보를 생성 할 수 밖에 없는 엠바 툴과는 다르죠.
: :
: : 델파이 Type Info Meta 내부 구조를 디테일하게 들어가려면 내용이 길어질거 같아 생략하고...
: : 엠바 C++ 컴파일러의 Lambda 버그 문제를 다시 짚어 봅시다.
: :
: :
: :
: : 엠바 툴만 사용하는 사람들은...
: : VC++ 컴파일러도 property 신택스를 지원하고 있다는 것을 모르고 있는 경우가 태반일 텐데...
: :
: : 다음과 같이 형식만 다를 뿐.. VC++ 컴파일러도 아주 오래전 부터 이미 property 신택스를 지원하고 있지요.
: :
: : __declspec(property(get = getter, put = setter)) propertyName;
: :
: :
: : 엠바 C++ 컴파일러에서 정의되어 있는 TStrings 클래스의 Values 프로퍼티를...
: : VC++ 프로퍼티 형식으로 표현하면 다음과 같이 표현 할 수 있고.
: :
: :
: : class TStrings : public System::Classes::TStrings
: : {
: : public:
: : 	String get_Value(const String& Name){ return __super::Values[Name]; }
: : 	void set_Value(const String& Name, const String& Value){ __super::Values[Name] = Value; }
: :   __declspec(property(get = get_Value, put = set_Value)) String Values[];
: : };
: : 

: :
: : VC++ 컴파일러의 property 신택스는 clang 컴파일러에서도 지원하므로 clang 컴파일러를 베껴서 만든
: : 엠바 C++ 컴파일러에서도 적용할 수 있습니다. VC++ 컴파일러가 산업계에서 가장 많이 대중적으로 사용되는
: : 메인스트림 컴파일러라 clang 도 VC++ 신택스를 지원하고 있는 거죠.
: :
: : 위와 같이 엠바 컴파일러에서 VC++ 형식으로 프로퍼티를 정의해서 사용하면...
: :
: : 질문에 언급되어 있는 구문은 다음과 같이 namespace 만 글로벌 네임스페이스로 지정해서 정상적으로 컴파일 할 수 있게 됍니다.
: :
: :
: : class TStrings : public System::Classes::TStrings
: : {
: : public:
: : 	String get_Value(const String& Name){ return __super::Values[Name]; }
: : 	void set_Value(const String& Name, const String& Value){ __super::Values[Name] = Value; }
: :   __declspec(property(get = get_Value, put = set_Value)) String Values[];
: : };
: : 
: : void __fastcall TForm2::Button1Click(TObject *Sender)
: : {
: :  auto Test{_STD make_unique< TStringList >()};
: : 
: :  [](auto v) {
: :     v->Values["Key"] = "Value";
: :     }((::TStrings*)Test.get());
: : }
: : 

: :
: : TStringList도 마찬가지 입니다.
: :
: :
: : 
: : class TStringList : public System::Classes::TStringList
: : {
: : public:
: : 	String get_Value(const String& Name){ return __super::Values[Name]; }
: : 	void set_Value(const String& Name, const String& Value){ __super::Values[Name] = Value; }
: :   __declspec(property(get = get_Value, put = set_Value)) String Values[];
: : };
: : 
: : void __fastcall TForm2::Button1Click(TObject *Sender)
: : {
: :  auto Test{_STD make_unique<::TStringList>()};
: : 
: :  // write
: :  [](auto v) { v->Values["Key"] = "Value"; }(Test.get());
: : 
: :  // read
: :  Caption = [](auto v) { return v->Values["Key"]; }(Test.get());
: : }
: : 
: : 

: :
: : 컴파일러를 엉터리로 만들어 놓았다는 게 감이 오나요?
: :
: :
: : 엠바 컴파일러에선...
: :
: : __property UnicodeString Values[const UnicodeString Name] = {read=GetValue, write=SetValue};
: :
: : [] 안에서 Name을 심볼명 처럼 쓰고 있는데, 이건 델파이 스타일 프로퍼티 신택스를 그대로 베껴서 쓴 산물에 불과한 거고.
: :
: :
: : VC++ 컴파일러 처럼 정의하는 게
: :
: :  __declspec(property(get = get_Value, put = set_Value)) String Values[];
: :
: : C++ 문법에 맞는 겁니다.
: :
: :
: : 위에서 __super는 패런트의 Context를 참조할 수 있도록 해주는 VC++ 컴파일러 키워드고
: : VC++ 컴파일러가 메인스트림 컴파일러로 가장 많이 쓰이는 컴파일러라 clang 컴파일러도 이 키워드를 지원하고 있지요.
: :
: :
: :
: : 결론...
: :
: :
: : 람다에서 outter scope를 참조하고 있지않고, 람다 인수로 넘어온 파라미터만 참조하고 있을 뿐인데도
: : 엠바 C++ 컴파일러에서 에러가 발생하는 이유는...
: :
: :
: : 엠바가 clang 컴파일러를 엉터리로 베껴서 만들어서...
: : 소스코드 파싱시... 람다 구문에서 프로퍼티가 Write(setter 형식) 형식으로 확장될 때...
: : Name을 outter scope 참조가 필요한 외부 심볼로 엉뚱하게 파싱하고 있기 때문 입니다.
: :
: :
: : 엠바 C++ 컴파일러는 clang을 베껴서 만들었고..
: : clang에선 이미 VC++ 형식의 property 신택스를 지원하고 있으므로 clang 컴파일러 파서의 property 핸들링 소스코드만
: : 잘 활용했더라도 문제가 없었을 텐데... 델파이 스타일 프로퍼티 신택스를 그대로 베껴서 컴파일러를 엉터리로 만든 바람에
: : 이와 같은 컴파일러 버그를 낳게 된 거죠.
: :
: :
: :
: :
: : IDE, Compiler, Debugger, LSP, RTL 등등
: :
: : 디테일하게 들여다 보면 엠바 툴은 문제가 너무 많아요. 아마추어가 만들어 놓은 것 처럼...
: :
: :
: :
: :
: :

+ -

관련 글 리스트
76041 lambda expression 에서 parameter의 property에 쓰기시 this 가 implicit capture 되는 문제 아루스 1519 2021/02/10
76042     Re: lambda expression this 가 implicit capture 되는 문제. 엠바 컴파일러 버그임. 빌더(TWx) 1810 2021/02/10
76073         Re:Re: lambda expression this 가 implicit capture 되는 문제. 엠바 컴파일러 버그임. 아루스 1304 2021/03/04
76048         Re:Re: 내공이 엄청나시네요 우인텍크 1552 2021/02/16
76049             Re:Re:Re: 내공이 엄청나시네요 1412 2021/02/16
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.