아이티랩 - ‘기차모델’로 갈아탄 ‘C++17’이 가져온 변화는?

C++17이 정식으로 승인됐습니다.

지난 9월6일, C++ 표준화 기구의 의장인 허브 서터가 자신의 블로그에 위 제목으로 C++17 표준안이 ISO의 최종 심의 절차에서 만장일치를 통해 승인됐다는 글을 올렸습니다.

이 소식을 듣고 아직 C++11에서 가져온 변화에도 적응하지 못했는데 벌써 C++17 표준이 나왔다는 사실에 놀라는 분들도 계실 것입니다. 한편 C++ 표준에 계속해서 관심을 갖고 계신 분들이라면 이제서야 C++17 표준이 마무리된 것인가 하고 의아해하는 반응을 보일 분도 계시리라 생각됩니다. 이러한 반응들은 모두 예상할 수 있습니다. 왜냐하면 놀랍게도 C++17 표준은 갑자기 완성된 것이 아니라, 오히려 그 반대인 지난 3년간 꾸준히 발전해 왔기 때문입니다. 2011년에 C++11 표준이 발표된 후, 2014년에 C++14 표준이 발표됐고, 계속해서 정기적인 C++ 커미티 미팅을 거치며 기능들이 제안되고, 토론을 통해 C++ 표준으로 수정·통합돼 왔습니다. C++17의 주요 기능 역시 이미 지난해 대부분 기술적으로 마무리된 것들이기도 합니다. C++ 표준화 기구에서는 도대체 지난 몇 년 간 어떤 일들이 벌어지고 있는 것일까요?

C++ 표준의 발전과 역사

googletag.cmd.push(function() { googletag.defineSlot('/6357468/0.Mobile_Article_intext_1_300_250', [300, 250], 'div-gpt-ad-1468307418602-0').addService(googletag.pubads());googletag.pubads().collapseEmptyDivs();googletag.pubads().enableSyncRendering();googletag.enableServices();googletag.display('div-gpt-ad-1468307418602-0'); });

C++은 1983년에 태어난 언어이므로, 30살이 훨씬 넘은 언어입니다. 그러나 첫 C++ 표준화는 1998년에 처음 이뤄졌습니다. 그래서 우리가 첫 번째 C++ 표준을 이야기할 때 그 기준은 1998년이라고 하고, C++98이라고 표현하기도 합니다. 98년도에 발표된 첫번째 C++ 표준은 7년간 21번의 미팅을 통해 완성됐습니다. 그리고 그 이후 5년간 C++ 표준화 위원회는 새로운 기능을 추가하기보다는 약간의 휴지기를 거치며 C++98 표준의 버그들을 수정한 03 표준(ISO/IEC 14882:2003)을 2003년도에 발표했습니다. 그리고 이어서 8년 간 21번의 미팅을 거쳐 첫 번째 표준에 크게 기능을 추가한 두 번째 메이저 표준인 C++11 표준을 2011년도에 발표했습니다. 특히 이 C++11은 C++98(03)과 비교해 다른 언어로 보일 만큼 많은 기능이 업데이트돼 C++ 개발자들에게 C++ 언어는 오래되고 정체된 언어가 아니라 계속해서 발전하는 언어라는 깊은 인상을 남겼습니다. 뒤이어 3년, 6번의 미팅을 거쳐 C++11의 마이너 업데이트인 C++14 표준을 만들어냈습니다.

C++ 표준화, ‘기차 모델’로 갈아타다

허브 서터 커미티 의장은 C++11 표준이 발표된 후 그 시점부터 C++ 표준화 위원회의 운영을 조금 다른 방식으로 가져가기로 합니다. C++11 표준이 완성될 때 까지 그 과정을 비교적 조용히 드러내지 않고 활동해 왔던 것과는 달리 그 시점부터는 다음 설명하는 방식들을 통해 활발하게 표준화 과정을 진행하기로 합니다. C++11 표준화를 진행할 때에는 ‘언제까지’라는 마감기한을 못박아두지 않은 채 최종 표준안을 발표할 수 있을 정도로 다 완성되면 내놓겠다고 하면서 말이죠. 또한 C++11에 포함될 ‘기능(Features)들’에만 집중했기 때문에 표준 출시가 계속 지연되는 문제(커미티가 막판에 디자인을 계속해서 바꿈)가 있었습니다. 그래서 C++03 표준안을 낸 후, 차기 표준안의 이름이었던 C++0x는 결국 200x년도가 아닌 2011년에야 C++11 이름을 달고 발표됐습니다. 그 과정에서 C++0x에서 x는 실은 10진수가 아닌 16진수 값이었다는 농담도 나왔습니다. 또한 이러한 진행 방식으로 인해 이 시기에서는 2004년에 가승인(draft)된 표준안도 공식 C++11에 포함돼 출시되기만을 마냥 기다려야만 했습니다.

C++11 표준화를 진행하며 얻은 경험으로 C++ 표준화 위원회는 ‘무엇’을 내놓을지도 중요하지만, ‘언제’ 내놓는 것 역시 매우 중요하다는 걸 깨달았습니다. 그래서 C++11 표준이 출시된 뒤부터는 방법을 달리 가져가기로 결정합니다. 3년마다 표준을 출시하기로 결정하고, ‘언제’를 더 중요하게 다루기 시작한 것입니다. 이것을 ‘기차 모델‘이라고 불렀습니다. 또한 우리가 개발을 진행하며 별도로 구분되는 새로운 기능들을 ‘브랜치’를 따서 작업하는 것처럼, 표준화 스펙에서도 ‘모듈, 파일 시스템, 네트워킹 표준 라이브러리’와 같이 개별 기술 묶음들을 TS(Technical Specification)라는 이름의 실험 기술(베타) 브랜치로 동시에 진행했습니다. 해당 TS 스펙이 충분히 표준화되기에 무르익으면 트렁크(C++ 표준)에 머지(merge)하는 전략을 가져갑니다. 그 과정에서 만약 표준화 기차가 도착했지만(3년마다 돌아오는 C++표준 발표 시기까지) 스펙이 충분하게 완성되지 않았다면 그 TS는 다음 표준 기차를 타게 되는 것입니다.

이러한 새로운 전략에 따라 3년이라는 시간이 지나 2014년 개정된 C++14 표준안을 내놓을 수 있었으며, 다시 3년 만에 정확히 돌아온 기차를 타고 2017년 C++17 표준을 내놓을 수 있게 된 것입니다. 마찬가지로 지난 2017년 7월 토론토 미팅을 통해 방금 C++20을 향하는 기차가 막 출발했고, 우리는 앞으로 3년 뒤 C++20이라는 기차가 도착할 것을 예상할 수 있게 된 것입니다.

C++ 위원회 미팅

현재 C++ 표준화 위원회는 일년에 세 번씩 미팅을 진행하고 있으며, 그 정보들은 C++ 표준화 위원회의 공식 사이트에서에서 확인할 수 있습니다. 최근에 있었던 미팅들과 주요 사건들을 나열해보자면 다음과 같습니다.

연도 장소 트립 리포트  주요 사건
2015년 5월 렉사나, 미국 [링크] 표준 스펙 버그 수정
Transactional Memory TS, Parallelism TS 표준 발표
2015년 10월 코나, 미국 [링크1]
[링크2]
Concurrency TS 표준 발표
2016년 2월 잭슨빌, 미국 [링크] 다음 TS들이 C++ 표준으로 합쳐짐
– Parallelism TS(Parallel STL)
– Library Fundamental 1 TS: any, optional, string_view
– File System TS
2016년 6월 올루, 핀란드 [링크1]
[링크2]
1. 다음 기능들이 표준 draft로 포함됨
– structured binding, if (init;condition)
– variant<>2.C++17 feature가 마무리되고 리뷰 기간에 들어감
2016년 11월 이사퀘어, 미국 [링크] ISO 리뷰 커멘트를 해결함
2017년 2월 코나, 미국 [링크] 1. C++17이 기술적으로 마무리 됨
2. 마지막 ISO 승인(balloting)을 위해 보내짐
3. 버그 수정
2017년 7월 토론토, 캐나다 [링크] C++20을 위한 첫번째 미팅
2017년 11월 엘버커키, 미국 [링크]

C++17 표준이 가져온 변화들

C++17 표준안은 어떤 새 기능들을 포함했고, 어떤 변화를 가져오게 할까요? 새로 발표된 C++17의 표준 가운데 개인적으로 주목할만하다고 생각되는 몇 개의 내용을 살펴보겠습니다. 아래의 예제 코드들은 표준 문서, 블로그 또는 컨퍼런스 등을 통해 발표된 자료들로부터 가져왔으며, 출처는 함께 표시했습니다.

1. 언어(C++ 문법)에서의 변화

a. If and switch with initializer

if (init; condition) 또는 switch (init; condition) 구문처럼 if/switch 안에 조건문과 선언문을 함께 사용할 수 있습니다. 과거에 RAII를 활용한 lock_guard를 사용해야 할 때, 그 lock에 대한 필요성이 전체 scope에 대해서는 필요없는 경우라면 좌측 테이블처럼 {} 괄호를 더 사용해 인스턴스의 lifetime을 제한하기도 하였습니다. 그러나 이젠 if 문 안에 선언문을 넣을 수 있으므로 우측과 같이 사용 가능합니다.

b. Structured bindings

배열, tuple, pair가 주어졌을 때 그 안에 담긴 개별 값들에 대해 로컬 변수 선언과 값 저장을 한 번에 할 수 있도록 합니다.

a와 b의 변경점을 모아서 함께 활용해 본다면, 다음과 같은 코드도 이제 C++17에서는 사용가능합니다. std::map의 insert는 삽입된 iterator와 성공여부를 가리키는 pair를 반환하므로, insert() 를 호출하고 그 성공 여부를 체크하는 동작을 if 구문 한 줄에서 아래처럼 작성이 가능합니다.

c. 기타 중요한 변경 사항들

– Template argument deduction for class templates [링크]
– constexpr if [링크]
– fold expression [링크]

2. 표준 라이브러리에서 변경된 점

a. std::string_view [링크]

std::string_view는 기존 std::string을 사용할 때 불필요하게 일어날 수 있었던 임시 객체 생성을 막을 수 있도록 고안된 클래스입니다. 내부적으로 문자열에 대한 pointer와 length만 가지므로 복사가 쉽고, 메모리를 할당하지 않습니다. std::string 인터페이스와 거의 동일하므로 기존 std::string을 사용하던 코드에서 std::string을 std::string_view로 변경하는 것만으로 쉽고 간단하게 성능상의 이득을 얻을 수 있을 것으로 예상됩니다. 다음 코드는 동일한 역할을 하는 코드지만, C++17 코드에서는 문자열의 복사가 일어나지 않습니다.

▲출처: https://youtu.be/LvwXJjRQfHk

b. std::variant [링크]

boost 라이브러리에 존재하던 variant 타입이 C++ 표준 라이브러리에 머지됐습니다.

▲출처: https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/

추가로 눈여겨 볼만한 C++17 새 라이브러리에는 std::optional<>, std::any<>가 있습니다.

C++의 다음 기차, C++20

다음 표준이 될 C++20에는 C++0x 시절부터 논의돼 온 Concept 기능이 드디어 포함될 예정입니다. 특히 코루틴, 네트워킹, 모듈 등이 모두 표준에 포함될 것으로 보여 C++20 역시 큰 변화를 맞이할 것으로 예상됩니다. 마지막으로 현재 각 컴파일러 벤더 별 C++17 지원사항은 다음 페이지에서 확인 가능합니다.

컴파일러 지원 상황

– Clang: https://clang.llvm.org/cxx_status.html
– GCC: https://gcc.gnu.org/projects/cxx-status.html
– MSVC: https://blogs.msdn.microsoft.com/vcblog/ (비주얼 스튜디오 업데이트를 통해 지원이 추가될 때마다 새 글을 통해 공유합니다)

글쓴이 | 김희준. 개발자의 가장 중요한 덕목은 ‘호기심’이라고 생각하고, 늘 기반기술을 연구하는 것을 좋아합니다. 다양한 분야에 관심을 갖고 공부하며, 그 결과를 https://heejune.me/ 블로그와 https://github.com/heejune/에서 나누고 있습니다.

의견 0 신규등록      목록