C++26: 리플렉션, 메모리 안전성, 계약, 그리고 새로운 Async 모델
Source: Hacker News
C++26 표준 초안이 이제 완성되었으며, 이는 오랜 기간 C++ 전문가이자 ISO C++ 표준 위원회 전 의장이었던 Herb Sutter가 보고했습니다. 최종 초안은 리플렉션을 도입하고, 코드 재작성 없이 메모리 안전성을 강화하며, 새로운 assert 문과 함께 전조건 및 후조건을 포함한 계약을 추가하고, 동시성 및 병렬성을 위한 통합 프레임워크를 구축합니다.
Reflection
Reflection은 Sutter가 설명하듯이 개발자에게 C++ 내부 메커니즘에 대한 열쇠를 제공하는 메커니즘으로, 언어가 스스로를 기술하고 코드를 생성하도록 하여 메타프로그래밍을 위한 견고한 기반을 제공합니다. C++의 정신에 충실하게, reflection은 런타임 오버헤드가 없습니다.
기본 예시는 reflection이 C++ 인터페이스를 선언하기 위한 특수 구문을 어떻게 가능하게 하는지 보여줍니다:
class(interface) IFoo {
int f();
void g(std::string);
};
//-- will be translated into the "classical":
class IFoo {
public:
virtual int f() = 0;
virtual void g(std::string) = 0;
virtual ~IFoo() = default;
IFoo() = default;
protected:
IFoo(IFoo const&) = default;
void operator=(IFoo const&) = default;
};
interface 추상화는 **cppfront, 순수 ISO C++로 컴파일되는 컴파일러**의 일부이며, Sutter가 제안들을 빠르게 실험하기 위해 만들었습니다. cppfront에는 copyable(복사/이동 생성·할당을 지원하는 타입을 표현), ordered( operator<=> 로 전체 순서를 정의하는 타입), union(이름이 붙은 태그드 유니온), regex 등과 같은 추상화도 포함됩니다.
Reflection은 많은 맞춤형 새로운 언어 기능에 대한 필요성을 줄여 C++의 미래 발전을 단순화할 수 있습니다. 이제 이러한 기능들을 재사용 가능한 컴파일‑타임 라이브러리로 표현할 수 있어 설계가 빠르고, 테스트가 용이하며, 처음부터 이식성이 확보됩니다.
메모리 안전
C++26은 메모리 안전성에서 상당한 개선을 제공합니다. 이 변경 사항은 초기화되지 않은 로컬 변수를 읽을 때 발생하는 undefined behavior를 제거하고 vector, span, string, string_view 등을 포함한 대부분의 표준 라이브러리 타입에 대한 경계 안전성을 제공합니다. 이러한 향상은 이미 Apple과 Google의 프로덕션 환경에 배포되어 수억 줄에 달하는 C++ 코드에 적용되었습니다.
- Google만 해도 새로운 안전 메커니즘으로 1,000건 이상의 버그가 수정되었으며, 연간 1,000~2,000건의 버그를 예방할 것으로 예상되고, 프로덕션 전체에서 세그멘테이션 오류 발생률을 30 % 감소시켰습니다.
- 이러한 이점은 기존 코드를 새로운 컴파일러로 다시 컴파일하기만 하면 얻을 수 있었으며, 메모리 안전성을 포기하도록 선택해야 했던 경우는 정교한 API를 통해 단 7건에 불과했습니다.
계약
C++26은 방어적 프로그래밍을 언어에 도입하여 기능적 안전성과 메모리 안전성을 향상시킵니다. 계약을 사용하면 개발자는 메서드 실행 중에 위반되어서는 안 되는 전조건(pre‑conditions)과 후조건(post‑conditions)을 표현할 수 있습니다. 또한 함수 선언에 어설션을 배치할 수 있어 호출자와 정적 분석 도구에 가시성을 제공합니다.
C++에서는 계약 위반을 처리하는 네 가지 방법을 제공합니다:
- ignore – 아무 것도 하지 않음.
- observe – 런타임에 위반을 보고함.
- enforce – 프로그램을 종료함.
- quick enforce – 진단 정보 없이 빠르게 종료함.
추가로, C의 assert 매크로를 대체하는 네이티브 어설션 메커니즘이 제공되어 불변 조건을 보다 통합된 방식으로 강제할 수 있습니다.
동시성 및 병렬성
C++26은 동시성 및 병렬성을 표현하고 제어하기 위한 프레임워크로 std::execution을 도입합니다. 세 가지 주요 추상화는 schedulers, senders, receivers이며, 이들은 사용자 정의 가능한 비동기 알고리즘 집합을 통해 조합될 수 있습니다. std::execution은 C++20 코루틴과 원활하게 작동하도록 설계되었으며, 구조화된 (엄격히 수명‑중첩된) 동시성 및 병렬성을 사용하는 프로그램을 더 쉽게 작성할 수 있게 해 주어, 설계 단계에서 데이터 레이스가 없는 실행을 보장합니다.
컴파일러 지원
두 주요 C++ 컴파일러인 GCC와 Clang은 표준화 과정에서 이미 C++26 기능 대부분을 구현했으며, 이 기능들은 곧 메인라인 릴리스에 포함될 예정입니다.