본문 바로가기

C/C++

[Google C++ Style Guide] 5. Other C++ Features

Google C++ Style Guide

 

 

5. Other C++ Features

 

A.     Reference Arguments (참조자 인자)

참조자로 넘겨지는 모든 파라미터는 const 를 붙인다.

 

정의 :

C에서는 함수의 파라미터를 수정할 필요가 있을 때포인터를 사용한다int foo(int *pval).  C++에서는 그 대안으로 파라미터를 참조자로 선언할 수 있다int foo(int &val).

 

장점 :

참조자로 파라미터를 정의하면(*pval)++과 같은 지저분한 코드를 피할 수 있다복사 생성자와 같은 함수들에게 필요하다참조자는 포인터와 달리 NULL값이 불가능하다.

 

단점 :

참조자는 포인터 의미가 아닌 변수 구문을 갖기에 혼동될 수 있다.

 

결론 :

 함수 파라미터에서 모든 참조자는 const 이어야 한다.

void Foo(const string &instring *out);

 

input 파라미터가 변수이거나 const 참조자이고, output 파라미터를 포인터로 하는 것은 구글 코드에서 매우 강한 관례(convention)이다. Input 파라미터는 const 포인터일수도 있지만절대 non-const 참조자는 허용하지 않는다.

 

input 파라미터가 const인 경우에복사되지 않는다는 것을 강조하려면그 객체의 lifetime동안 존재해야 하고이를 주석으로 달아놓는다.

 

 

B.      Function Overloading (함수 오버로딩)

어떤 오버로드 함수가 호출되는지 몰라도어떻게 동작하는지 이해할 수 있을 때에만 오버로드된 함수(생성자 포함)를 사용한다. ???

 

정의 :

const string& 을 갖는 함수와 다른 파라미터 const char*를 갖도록 오버로딩 한다.

class MyClass {

 public:

  void Analyze(const string &text);

  void Analyze(const char *textsize_t textlen);

};

 

장점 :

오버로딩은 동일한 이름의 함수가 다른 파라미터를 갖도록 하여 코드를 직관적으로 만든다.

 

단점 :

함수가 단지 파라미터 타입에 의해서만 오버로드되면, C++의 복잡한 매칭 룰(matching rule)을 이해해야 한다또한 파생 클래스가 여러가지 함수를 오버라이딩한다면상속의 의미와 혼란을 일으킬 것이다.

 

결론 :

함수를 오버로딩하고 싶으면파라미터에 대한 정보를 가지고 네이밍할 수 있는지 검토한다Append()보다는 AppendString()AppendInt()가 낫다.

 

 

C.      Default Arguments (디폴트 인자)

아래 설명하는 특별한 상황을 제외하고디폴트 함수 파라미터를 허용하지 않는다.

 

장점 :

함수는 종종 많은 디폴트 값을 사용하지만때때로 그 디폴트 값을 오버라이딩하길 원한다디폴트 파라미터는 예외에 대해서 많은 함수를 정의하지 않고 사용할 수 있게 해준다.

 

단점 :

때때로 API를 어떻게 사용하는지를 보고 API를 이해한다이전 코드를 copy-and-paste하면 모든 파라미터가 드러나지 않기 때문에 디폴트 파라미터를 유지보수하기 어렵다. Copy-and-paste는 디폴트 파라미터가 새로운 코드에 적합하지 않을 때 문제가 발생한다.

 

결론 :

아래 제시된 코드를 제외하고 모든 파라미터는 명시적으로 기술되야 한다.

하나의 특별한 예외는 디폴트 파라미터가 변수 길이 파라미터 리스트를 시뮬레이션할 때이다.???

 

// Support up to 4 params by using a default empty AlphaNum.

string StrCat(const AlphaNum &a,

               const AlphaNum &b = gEmptyAlphaNum,

               const AlphaNum &c = gEmptyAlphaNum,

               const AlphaNum &d = gEmptyAlphaNum);

 

 

D.     Variable-Length Array and alloca() (가변 배열과 alloca() )

가변 배열이나 alloca()를 사용하지 않는다.

 

장점 :

가변 배열은 보기에 자연스러워 보인다가변 배열과 alloca()는 매우 효율적이다.

 

단점 :

가변 배열과 alloca는 표준 C++이 아니다더 중요한 건데이터에 따라 스택의 공간을 할당하는 양이 다르다따라서 메모리 침범 버그를 발견하기 어렵다. “많은 머신에서 잘 돌아가지만불가사의하게 프로그램이 죽을 것이다.”

 

결론 :

 vector string으로 대체할 수 없다면(EC++), 대신 scoped_ptr / scoped_array와 같은 안전한 할당자를 사용한다.

 

 

E.      Friends (프렌드)

특별한 이유가 있을 경우, friend 클래스와 함수를 사용한다.

 

friend는 항상 클래스의 private 멤버의 사용을 찾기 쉽도록 하기 위해 같은 파일에 정의한다. Foo 클래스의 friendFooBuilder를 선언해서 외부에 상태를 노출시키지 않고 Foo의 내부 상태를 조작할 수 있다. Unittest 클래스를 테스트 하려는 클래스의 friend로 만들면 유용하다.

 

단지 하나의 다른 클래스가 그 클래스의 멤버에 접근할 때, public 멤버를 만드는 것보다 friend 를 사용한다.

 

 

F.      Exceptions (예외)

C++ 예외를 사용하지 않는다.

 

장점 :

 예외는 어플리케이션의 상위 수준에서 발생할 수 없는’ 에러를 처리할 수 있도록 한다.

 예외는 다른 현대 언어에서 많이 사용된다. C++에서의 예외 사용은 Python, Java, C++과 일관성을 갖도록 한다.

 일부 third-party C++ 라이브러리는 예외를 사용하고내부적으로 그것을 off시켜 다른 라이브러리와의 통합을 어렵게 한다.

 예외는 생성자가 실패하는 유일한 방법이다팩토리 함수나 Init()메소드로 실험할 수 있지만 상대적으로 heap allocation이나 새로운 유효하지 않은 상태가 요구된다.

 예외는 테스팅 프레임워크에서 정말로 편리하다.(handy)

 

단점 :

 기존 함수에서 throw 구문을 추가할 때그 함수 상위로의 모든 호출 함수를 살펴봐야 한다예외 발생시 함수들이 제대로 clean up 되지 않을 수가 있다.

 프로그램의 제어 흐름을 파악하기 힘들다함수가 기대하지 않는 곳에서 리턴할 것이다이것은 유지보수와 디버깅을 힘들게 한다.

 예외 안전은 RAII(Resource Acquisition is Initialization)와 다른 코딩 연습을 요구한다예외를 허용하는 것은 그것이 가치가 없을지라도 비용이 발생한다.

 컴파일 타임이 약간 증가하며 주소 공간 압박도 증가한다.

 예외를 사용하면 개발자가 코드가 적합하지 않고 안전하지 못할 때 예외를 던지도록 부추긴다예를 들어 사용자 입력 에러를 예외로 던지면 안된다.

 

결론 :

예외의 장점에는 많은 비용이 따른다특히 새로운 프로젝트일 때그러나 기존 코드에 대해 예외를 사용하면 모든 의존된 코드에 영향을 준다예외가 새로운 프로젝트에 적용되었을 때그 새로운 프로젝트를 기존의 예외 없는 코드에 통합할 때 문제가 발생한다.

예외에 대한 대안으로 에러 코드를 사용하거나 assertion 을 사용하는 것이 낫다.

 

 

G.     Run-Time Type Information(RTTI) (런타임 타입 정보)

런타임 타입 정보(RTTI)를 사용하지 않는다.

 

정의 :

RTTI는 프로그래머가 런타임에 C++ 클래스의 타입을 알 수 있게 한다.

 

장점 :

일부 유닛테스트에 유용하다예를 들어 새로 생성된 클래스가 동적 타입을 갖는지 검증하기 위한 팩토리 클래스를 테스트하는데 유용하다.

드문 경우에 테스트 외부에서도 유용하다.

 

단점 :

런타임에 타입을 알아야 한다는 건 디자인에 문제가 있다는 것을 의미한다.

 

결론 :

유닛 테스트를 제외하고 RTTI를 사용하지 않는다.

대안으로 가상 함수는 특정 서브 클래스의 타입에 따라 다른 코드의 경로를 실행한다작업이 객체 외부에 있다면 Visitor 디자인 패턴 같은 double-dispatch 솔루션을 고려한다.

이러한 아이디어들을 사용할 수 없다면, RTTI를 사용한다그러나 두 번 생각해라.

 

 

H.     Casting (캐스팅)

static_cast<>()와 같은 C++ 캐스팅을 사용한다. int y = (int) x; 혹은 int y = int(x); 와 같은 캐스팅은 사용하지 않는다.

 

정의 :

C++은 캐스팅 연산 타입을 구분하기 위해 C와는 다른 캐스팅 시스템이 있다.

 

장점 :

캐스팅의 문제는 연산이 모호하다때로는 conversion((int)3.5 ), 때로는 cast((int)”hello” )

C++캐스팅은 이 문제를 피한다게다가 캐스팅을 검색할 때 눈에 잘 띈다.

 

단점 :

코드가 지저분하다.

 

결론 :

C-style 캐스팅은 사용하지 말고, C++-style 캐스팅을 사용한다.

-       값을 변환(conversion)할 때static_cast 를 사용한다.

-       const를 제거하기 위해 const_cast를 사용한다.

-       Int pointer 타입으로의 불안전한 변환을 할 때 reinterpret_cast를 사용한다사용 목적과, aliasing issue를 이해할 때에만 사용한다.

-       테스트 코드를 제외하고 dynamic_cast를 사용하지 않는다유닛 테스트 외부에서 런타임에 타입 정보를 알 필요가 있다면 디자인 결함이다.

 

 

I.       Streams (스트림)

로그를 위해서만 스트림(<<)을 사용한다.

 

정의 :

스트림은 printf() scanf()의 대체물이다.

 

장점 :

스트림을 사용하면 출력하려는 객체의 타입을 알 필요가 없다인자 리스트에 매칭되는 포맷 스트링에 대한 문제도 없다스트림은 관련 파일을 열고 닫는 자동 생성자와 파괴자가 있다. ??

 

단점 :

스트림은 pread()와 같은 기능을 하기 어렵다스트림은 (%1s 명령어)와 같은 연산자 reordering (국제화에 유용)을 지원하지 않는다.

 

결론 :

로깅 인터페이스를 제외하곤 스트림을 사용하지 않는다대신 printf 같은 루틴을 사용한다.

스트림을 사용하는 다양한 장점과 단점에 대한 토론이 있지만구글에서는 스트림을 사용하지 않는다.

 

 

 

J.      Preincrement and Predecrement (전위증감 연산자)

iterator와 다른 템플릿 객체에 대해 ++i를 사용한다.

 

정의 :

변수가 증가(++i or i++)하거나 감소(--i or i--)할 때전위 연산자 또는 후위 연산자를 사용할지 결정해야 한다.

 

장점 :

리턴 값이 무시될 때전위 연산자(++i) (i++)보다 절대 덜 효율적이지 않으며종종 더 효율적이기 까지 하다후위 연산자는 i의 복사본을 요구하기 때문이다만약 i iterator이거나 다른 non-scalar 타입이라면 i의 복사 비용은 비싸다.

전위/후외 연산자가 같은 동작을 한다면왜 항상 전위 연산자를 사용하지 않을까?

 

단점 :

전통적으로 C에서는 후위 연산자를 사용했다특히 for 문에서영어처럼 주어(i)가 동사(++)의 앞에 두듯이 전위 연산자가 더 읽기 쉽다는 것을 발견했다.

 

결론 :

간단한 scalar(non-object)값에 대해서는 어떤 형태를 사용하던지 상관없지만, iterator와 다른 템플릿 타입에 대해서는 전위 연산자를 사용한다.

 

 

K.      Use of const (const 사용)

가능하면 const 사용을 강력히 추천한다.

 

정의 :

const 키워드를 사용해서 변수와 파라미터를 선언하는 것은 그 값이 변하지 않는다는 것을 의미한다 (const int foo). 클래스의 함수의 해당 클래스의 멤버 변수의 상태가 변경하지 않는다는 것을 나타내기 위해 const를 사용할 수도 있다 (class Foo { int Bar(char c) const; }; )

 

장점 :

변수가 어떻게 사용되는지 이해하기 쉽다컴파일러는 타입 체크가 쉬워지며 더 나은 코드를 만든다해당 변수가 수정되지 않는 다는 것을 한 눈에 알 수 있으며멀티 스레드 프로그램에서 lock을 사용하지 않고도 thread-safe하다

 

단점 :

const 는 바이러스성이다함수에 const 변수를 넘겨주려면함수 원형에 const로 선언해야 한다. (혹은 const_cast를 사용해야 한다). 이것은 특히 라이브러리 함수를 호출할 때 문제가 될 수 있다.

 

결론 :

const 변수데이터 멤버메소드파라미터는 컴파일 타임에 타입 체크를 하기 때문에 에러를 일찍 잡아낼 수 있다그래서 다음과 같은 상황일 때, const 사용을 강력히 추천한다.

함수가 참조자나 포인터에 의해 넘겨받은 파라미터를 수정하지 않으면그 파라미터는 const

가능할 때 언제라도 메소드는 const로 선언접근자는 거의 항상 const. 다른 메소드도 데이터 멤버를 수정하지 않으면 const.

데이터 멤버 변수가 생성된 이후에 수정될 필요가 없을 때는 const로 만드는 것을 고려한다.

 

그러나const int * const * const x; 와 같이 const를 남발해선 안된다이 코드가 문법적으로 맞을지라도 const int** x; 처럼 선언하면 충분하다.

 

mutable 키워드를 사용해도 되지만, thread-safe하지 않기 때문에 신중히 사용한다.

 

const 위치 :

const int* foo보다 int const *foo를 선호하는 사람이 있다일관성을 이유로 더 가독성이 있다고 주장한다. const는 그 다음에 나오는 객체를 묘사한다는 것이다그러나 명사(int)앞에 형용사(const)가 오는 영어 문법에 맞기 때문에, const를 먼저 쓰는 것(전자)이 더 가독성이 좋다.

 

const int* foo와 같이 먼저 쓰는 것을 권하지만코드에서 일관성 있게 사용하면 된다.

 

 

L.      Integer Types (정수 타입)

C++ 빌트인 정수형 타입은 int형만 사용한다다른 사이즈가 필요하면 int16_t 처럼 <stdint.h>내의 정확한 사이즈의 정수형 타입을 사용한다.

 

정의 :

C++은 정수형 타입의 사이즈를 명시하지 않는다전형적으로 short 16bit, int 32bit, long 32bit, long long 64bit라고 생각한다.

 

장점 :

선언의 일관성

 

단점 :

C++에서 정수형 타입의 사이즈는 컴파일러와 아키텍처에 따라 다르다.

 

결론 :

<stdint.h> int16_t, uint32_t, int64_t 등과 같은 타입을 정의하며정수 사이즈가 필요할 때는 short, unsigned long long과 같은 것보다는 <stdint.h>에 정의된 타입을 사용 한다. C의 정수형 타입은 int 만을 사용한다사이즈를 계산할 때는 size_t ptrdiff_t와 같은 표준을 사용해도 좋다.

 

루프문처럼 크지 않은 정수형을 위해 int를 사용한다. 64-bit 정수형이 필요하면 int64_t 혹은 uint64_t를 사용한다.

 

표현하고자 하는 양이 숫자라기보다 bit 패턴이고, 2의 보수 오버플로우를 정의할 필요가 있는 경우를 제외하고 uint32_t와 같은 unsigned 정수 타입을 사용하면 안된다특히 숫자가 절대 음수값을 가질 수 없다는 것을 표현하기 위해 unsigned 타입을 사용해선 안된다대신 assertion을 사용한다.

 

On Unsigned Integers

책 저자를 비롯한 일부 사람들은 절대 음수가 아닌 숫자를 표현하기 위해 unsigned 타입을 사용할 것을 추천한다그러나 아래와 같은 버그를 만들어 낼 수 있다.

for (unsigned int i = foo.Length()-1i >= 0; --i) ...

 

위 코드는 절대 종료되지 않는다때로 gcc는 이 버그를 발견하고 경고할지도 모르지만항상 그렇지는 않다. Signed unsigned 변수를 비교할 때도 버그가 발생할 수 있다.

 

따라서, assertion을 사용해서 변수가 non-negative라고 문서화 하고, unsigned 타입은 사용하지 않는다.

 

 

M.    64-bit Portability (64비트 호환성)

64bit 32bit 호환되게 코드를 작성한다. print, 출력구조체 정렬 등의 문제를 명심한다.

 

일부 타입에 대해 printf() 32-bit 64-bit 시스템에서 호환성이 없다. C99은 호환 가능한 포맷 지정자(specifier)를 정의하지만, MSVC 7.1은 이 지정자 일부는 이해하지 못하며표준도 일부 빠져있다그래서 어떤 경우에는 추한 버전을 정의해야 한다. (표준 include 파일인 inttypes.h의 스타일에서)

 

// printf macros for size_t, in the style of inttypes.h

#ifdef _LP64

#define __PRIS_PREFIX "z"

#else

#define __PRIS_PREFIX

#endif

 

// printf format string에서 % 다음에  macros 사용

// 32/64 bit 에서 모두 동작하려면아래와 같이 사용

// size_t size = records.size();

// printf("%"PRIuS"\n", size);

 

#define PRIdS __PRIS_PREFIX "d"

#define PRIxS __PRIS_PREFIX "x"

#define PRIuS __PRIS_PREFIX "u"

#define PRIXS __PRIS_PREFIX "X"

#define PRIoS __PRIS_PREFIX "o"

 

 

Type

DO NOT use

DO use

Notes

void * (or any pointer)

%lx

%p

int64_t

%qd, %lld

%"PRId64"

uint64_t

%qu, %llu, %llx

%"PRIu64", %"PRIx64"

size_t

%u

%"PRIuS", %"PRIxS"

C99 specifies %zu

ptrdiff_t

%d

%"PRIdS"

C99 specifies %zd

 

 

PRI* 매크로는 컴파일러에 의해 연결되는 독립적인 문자열을 확장한다그러므로 비상수 포맷 문자열을 사용한다면,이름보다는 포맷에 매크로의 값을 삽입한다. PRI* 매크로를 사용할 때 % 뒤에 문자열 길이 지정자를 포함시킬 수도 있다예를 들어printf(“x = %30”PRIuS”\n”, x)  32-bit 리눅스에 확장될 때 printf(x = %30” “u” “\n”, x)로 될 것이고 컴파일러는 printf(“x = %30u\n”, x)로 처리할 것이다.

 

- sizeof(void *) != sizeof(int) 이 둘은 같지 않다포인터 사이즈는 intptr_t를 사용한다.

 

구조체 정렬(alignment)에 주의할 필요가 있다. (특히 구조체가 디스크에 저장되는 방식). 64-bit 시스템에서 int64_t/uint64_t를 가지는 클래스/구조체는 디폴트로 8-byte로 정렬되게 끝난다디스크에 구조체를 저장해야 할 때는 구조체 정렬을 바꿔야 한다예를 들어, gcc에서는 __attribute__((packed)).  MSVC에서는 #pragma pack(), __declspec(align())등을 사용한다.

 

-64-bit 상수를 만들려면 LL이나 ULL 접미사를 사용한다.

 

int64_t my_value = 0x123456789LL;

uint64_t my_mask = 3ULL << 48;

 

- 32-bit, 64-bit 시스템에 다른 코드가 필요하면 #ifdef _LP64를 사용한다. (그러나 가능하면 피한다)

 

 

 

N.     Preprocessor Macros (전처리 매크로)

매크로는 조심한다매크로보다는 inline 함수, enum, const 변수를 선호한다.

 

매크로는 당신이 보는 코드와 컴파일러가 보는 코드가 다르다는 것을 의미한다이것은 예기치 못한 동작으로 이어질 수 있으며특히 매크로가 전역 범위라면 더 그렇다.

 

다행히 C와는 달리 C++에서는 거의 필요하지 않다성능에 중요한 코드를 인라인 하기 위해 매크로를 사용하는 대신, inline 함수를 사용한다상수를 저장하기 위해 매크로를 사용하는 대신, const 변수를 사용한다긴 변수 이름을 단축하기 위해 매크로를 사용하는 대신참조를 사용한다조건적 컴파일 코드를 위해 매크로를 사용하는 대신조건적 컴파일을 사용하지 않는다(물론 #define 보호는 제외). 이런 매크로가 테스트를 더 어렵게 만든다.

 

매크로는 다른 기술들이 할 수 없는걸 할 수 있으며자신의 코드에서 보이기도 한다특히 저수준 라이브러리에서문자열을 만들거나 합치거나 하는 등의 특별한 기능은 언어상에서 제공하지 않는다매크로를 사용하기 전에매크로를 사용하지 않고 구현할 수 있는지 고려한다.

 

다음은 매크로 사용시 피해야 할 패턴이다.

-       .h 파일에서 매크로를 정의하지 않는다

-       매크로를 사용하기 바로 전에 #define하고 사용한 바로 다음에 #undef 한다.

-       자신의 매크로 사용을 위해 기존의 매크로를 #undef하지 않는다유일한 이름을 쓴다.

-       Unbalanced C++ construct를 확장하기 위해 매크로를 사용하지 않는다.

-       함수/클래스/변수 이름을 만들기 위해 ##를 사용하지 않는다. ??

 

 

O.     0 and NULL

정수형에는 0실수형에는 0.0포인터에는 NULL, char에는 ‘\0’을 사용한다.

 

정수형에는 0실수형에는 0.0을 사용한다논쟁의 여지가 없다.

 

포인터(주소 값)에 대해서는 0 NULL에 대한 선택이 있다. Bjarne Stroustrup는 꾸미지 않은 0을 선호한다구글은 포인터처럼 보이기 때문에 NULL을 선호한다사실 gcc 4.1.0과 같은 일부 C++ 컴파일러는 ‘sizeof(NULL) sizeof(0)와 같지 않다와 같은 유용한 경고를 위해 NULL에 대한 특별한 정의를 제공한다.

 

char에 대해서는 ‘\0’을 사용한다올바른 타입이며 가독성도 좋다.

 

 

 

 

P.      Sizeof

가능하면 size(타입) 대신에 sizeof(변수명)를 사용한다.

 

변수 타입이 변할 수 있기 때문에 sizeof(변수명)을 사용한다.

Struct data;

memset(&data0sizeof(data));

 

memset(&data0sizeof(Struct));

 

 

Q.     Boost

부스트(boost) 라이브러리는 승인된 것만 사용한다.

 

정의 :

Boost library collection 인기 있는 peer-reviewed, free, open-source C++ 라이브러리 집합이다.

 

장점 :

부스트 코드는 품질이 높고이식성이 좋으며, type trait, 보다 나은 binder, 보다 나은 스마트 포인터와 같은 C++ 표준 라이브러리가 제공하지 못하는 중요한 부분을 제공한다.

 

단점 :

메타프로그래밍향상된 템플릿 기술 등과 같은 일부 부스트 라이브러리는 가독성을 해친다.

 

결론 :

코드 가독성과 유지보수를 위해 아래의 라이브러리만 허용한다.

-       Call Traits : boost/call_traits.hpp

-       Compressed Pair : boost/compressed_pair.hpp

-       Pointer Container : boost/ptr_container

(C++03 표준(ptr_circular_buffer.hpp 와 ptr_unordered*)에 없는 serialization wrapper 제외)

-       Array : boost/array.hpp

-       The Boost Graph Library (BGL) : boost/graph

(serialization(adj_list_serialize.hpp) parallel / distributed 알고리즘과 데이터 구조(boost/graph/parallel/*  boost/graph/distributed/*). 제외)

-       Property Map : boost/property_map

(parallel / distributed property maps (boost/property_map/parallel/* 제외).

-       Iterator 일부 : boost/iterator/iterator_adaptor.hpp, boost/iterator/iterator_facade.hpp, andboost/function_output_iterator.hpp

 

추후 다른 부스트 기능들도 추가할 예정이다.

 

R.     C++0x

C++0x의 승인된 라이브러리와 확장 기능만을 사용한다현재 승인된 것이 없다.

 

정의 :

C++0x는 차세대 ISO C++ 표준으로 비공식 명칭이다새로운 표준은 핵심 언어에 몇 가지 사항을 추가하고, TR1 라이브러리의 대부분(일부 특별한 수학 함수 제외)을 반영하여 C++ 표준 라이브러리를 확장할 것이다. (Wikipedia)

 

장점 :

C++0x는 차세대 표준이며결국 대부분의 C++ 컴파일러에 의해 지원될 것이라고 기대한다.

 

단점 :

C++0x는 이전보다 상당히 복잡하며(1,300page vs 800page), 많은 개발자에게 친숙하지 않다다양한 기능들이 gcc, icc, clang, Eclipse등과 같은 툴에 의해 동일하게 구현이될지 예측할 수 없다.

 

Boost처럼 C++0x 확장은 가독성을 해친다다른 확장은 기존의 메커니즘으로 이용 가능한 기능들을 복제했다이는 혼동을 주고 변환에 대한 비용을 지불하게 한다.

 

결론 :

승인된 C++0x 라이브러리와 언어 기능만을 사용한다현재 승인된 기능은 없으며추후 개별적으로 승인될 것이다.