템플릿 인자로 또 템플릿 타입을 받는 타입의 변수 선언이
A<B<C > > d;
이런 식으로 돼 있는 옛날 C++ 코드를 보니 문득 감회가 새롭다.
예전에는 템플릿 인자를 닫는 > 가 중첩될 때, 여러 >를 >>로 붙일 수가 없었다.
타입 선언인지 일반 연산인지 문맥을 고려하지 않는 전통적인 parser는, 이것을 비트 shift 연산자로 인식하기 때문이었다. 따라서 오류크리.
그래서 > 사이를 강제로 띄워 줘야 했는데 이것이 보기에 그리 좋지는 않음이 자명한 노릇이었다.
일단 C++ 계보의 언어들은 문법 차원에서 변수 선언을 명시하는 토큰이 없고(파스칼의 var과 콜론, 베이직의 Dim과 as 같은), 달랑 “타입 변수명”이라는 아주 문맥 의존적인 문법만을 바탕으로 변수 선언을 컴파일러가 알아서 추론해야 하기 때문에 파싱이 까다로운 게 사실이다. 게다가 C++부터는 변수 선언은 객체 선언과 동급이 되어, 함수 몸체 내부 어디에서나 마음대로 올 수 있지 않은가.
훗날 C++ 언어가 C++11로까지 확장되면서, 언어가 명시하는 스펙 자체가 바뀌면서 >>를 붙여 써도 괜찮게 되었다.
비주얼 C++의 경우, 2003은 >>가 확실하게 인식되지 않았는데, C++11이 정식으로 제정되기 전부터 2008쯤부터 이미 >>를 지원하고 있었다.
이런 문법의 변화로 인해, 클래스 A는 type을, 클래스 B는 int를 받는 템플릿 클래스라고 했을 때
A<B<30>>1> > p;
라는 코드가 과거에는 30>>1이 15라고 계산되어 컴파일이 되었지만, 이제는 되지 않는다. >>가 템플릿 인자를 닫는다는 의미로 먼저 인식되었기 때문이다. 이것은 함수 호출 문맥에서는 ,가 콤마 연산자가 아니라 인자 구분자로 먼저 인식되는 것과 비슷한 맥락이다.
바뀐 문법에서는
A<B<(30>>1)>> p;
라고, 뒤의 >를 붙일 수 있는 대신 진짜 템플릿 인자 내에서의 산술 연산은 괄호로 싸 줘야 <, > 사이의 모호성을 막을 수 있다.
사실, 템플릿 인자 안의 숫자는 어차피 컴파일 시점에서 값이 다 결정되는 것들이기 때문에, 복잡한 연산이 들어갈 일은 거의 없다. 산술 연산을 괄호로 반드시 싸야 하게 만들고 그 대신 템플릿 인자의 < >에 편의를 더 주는 것이 훨씬 더 합리적인 정책인 것이 사실이다.
뭐, 괄호도 해 주고 >를 띄워 주기까지 하면, 어느 구닥다리 C++ 컴파일러에서나.. 컴파일 가능한 코드를 만들 수 있긴 하지만, 미관은 제일 떨어지겠지. ㅋㅋ
그러고 보니 옛날에는 일반 함수 포인터 말고, C++ 멤버 함수 포인터를 명시할 때 그냥 이름만 써 줘도 괜찮은 수준이었는데
나중에는 반드시 &를 붙이고 scope도 명시해 줘야 하게 문법이 좀 더 엄격하게 바뀐 걸로 기억한다. 한 VC++ 2005쯤부터이다. for(int x=0; ... )에서 x의 scope만큼이나 전형적인 호환성 문제이다.
이렇듯 C++이 어제나 오늘이나 큰 뼈대는 변함없고 계속 새로운 기능이 추가만 되는 것 같아도,
이미 있던 문법도 야금야금 바뀌어 온 게 좀 있다.
Posted by 사무엘