From 70af8402e735391c5c4749cf6ca487b927b2755a Mon Sep 17 00:00:00 2001 From: luncliff Date: Tue, 2 Jul 2019 22:45:07 +0900 Subject: [PATCH 1/7] broken links: Expression --- sections/Expr.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sections/Expr.md b/sections/Expr.md index 4c70d24..3230873 100644 --- a/sections/Expr.md +++ b/sections/Expr.md @@ -2389,7 +2389,7 @@ C 스타일 타입변환이 위험한 이유는 어떤 형태로의 변환도 ##### Enforcement * `const_cast`를 지적한다. -* 이 규칙은 [타입 안정성 분석](#Pro-type-constcast)과 관련 있다 +* 이 규칙은 [타입 안정성 분석](./Profile.md#Pro-type-constcast)과 관련 있다 ### ES.55: 범위 검사가 필요없게 하라 @@ -2416,7 +2416,7 @@ C 스타일 타입변환이 위험한 이유는 어떤 형태로의 변환도 복제를 막고 성능을 향상시키기 위해 복사보다는 이동을 사용한다. -이동 연산은 보통 빈 개체를 남긴다 ([C.64](#Rc-move-semantic)). 이는 기대밖의 결과 혹은 위험으로 이어질 수 있다. 가능하다면 lvalue로부터 이동하는 것을 피하려 해야한다 (lvalue에 나중에 접근할 수도 있다). +이동 연산은 보통 빈 개체를 남긴다 ([C.64](./Class.md#Rc-move-semantic)). 이는 기대밖의 결과 혹은 위험으로 이어질 수 있다. 가능하다면 lvalue로부터 이동하는 것을 피하려 해야한다 (lvalue에 나중에 접근할 수도 있다). ##### Notes @@ -2787,7 +2787,7 @@ C 스타일 `(T)e`변환과 함수형 타입변환 `T(e)`를 지적한다 이 규칙은 명백하고 잘 알려진 언어 규칙이지만, 따르기 어렵다. 큰 부담(overhead)없이 이 규칙을 준수하기 위해서는 좋은 코딩스타일, 라이브러리 지원, 그리고 정적 분석기가 필요하다. -[C++'s resource- and type-safety model](#Stroustrup15) 논의에서의 중요 부분 중 하나다. +[C++'s resource- and type-safety model](./Bibliography.md#Stroustrup15) 논의에서의 중요 부분 중 하나다. ##### See also @@ -2796,7 +2796,7 @@ C 스타일 `(T)e`변환과 함수형 타입변환 `T(e)`를 지적한다 * 수명주기 문제를 피하려면 [shared_ptr](#Rf-shared_ptr)를 사용하라 * `nullptr`가 허용되지 않는다면 [references](#Rf-ptr-ref)를 사용하라 * 의도치 않은 `nullptr`를 일찍 잡아내기 위해 [not_null](#Rf-not_null)을 사용하라 -* Use the [bounds profile](#SS-bounds) to avoid range errors. +* 범위 오류를 피하고 싶다면 [경계 안전성 프로필](./Profile.md#SS-bounds)을 참고하라 ##### Example @@ -3859,8 +3859,9 @@ C 스타일 문자열을 사용한다면 ``의 함수들을 잘 알아 예시와 같은 (완전히 합법인) 생성 코드는 실제로는 찾아내기 어렵고 많은 오류의 원인이다. 다음과 같은 코드를 고려해보라: + ```c++ - unsigned area(unsigned height, unsigned width) { // [see also](#Ri-expects) + unsigned area(unsigned height, unsigned width) { // see also: I.6 사전 조건을 표현하고 싶다면 `Expects()`를 사용하라 return height * width; } // ... From 486fb531b6df9cf43b5257f9a7a8f969d55605e7 Mon Sep 17 00:00:00 2001 From: luncliff Date: Wed, 3 Jul 2019 00:23:34 +0900 Subject: [PATCH 2/7] broken links: Intro, Interface --- sections/Interfaces.md | 34 ++++++++--------- sections/Introduction.md | 80 ++++++++++++++++++++-------------------- 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/sections/Interfaces.md b/sections/Interfaces.md index 5824995..6c23287 100644 --- a/sections/Interfaces.md +++ b/sections/Interfaces.md @@ -143,7 +143,7 @@ ##### References -[함수 호출에 대한 규칙](#SS-call) +[함수 호출에 대한 규칙](./Functions.md#SS-call) ##### Note @@ -364,7 +364,7 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 ##### References -`Expects()`는 [GSL](#S-gsl)에 기술되어 있다. +`Expects()`는 [GSL](#./GSL.mdS-gsl)에 기술되어 있다. ##### Note @@ -418,7 +418,7 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 ##### Note -`unsigned`를 사용하는 것은 [값이 음수가 아니라고 보장하는](#Res-nonnegative) 문제를 회피하는 좋은 방법이 아니다. +`unsigned`를 사용하는 것은 [값이 음수가 아니라고 보장하는](./Expr.md#Res-nonnegative) 문제를 회피하는 좋은 방법이 아니다. ##### Enforcement @@ -513,7 +513,7 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 이제 버그가 분명하게 보인다. (단, 주석을 읽는 사람에게만 보인다.) -더 나은 방법은 [RAII](#Rc-raii)를 사용해 사후 조건("잠금을 해제해야 함")이 코드에 적용되도록 하는 것이다: +더 나은 방법은 [RAII](./Class.md#Rc-raii)를 사용해 사후 조건("잠금을 해제해야 함")이 코드에 적용되도록 하는 것이다: ```c++ void manipulate(Record& r) // best @@ -559,7 +559,7 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 ##### Alternative -이 리소스는 반드시 해제되어야 한다" 형태의 사후 조건은 [RAII](#Rc-raii)를 통해 가장 잘 나타낼 수 있다. +이 리소스는 반드시 해제되어야 한다" 형태의 사후 조건은 [RAII](./Class.md#Rc-raii)를 통해 가장 잘 나타낼 수 있다. ##### Note @@ -600,7 +600,7 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 ##### See Also -[제너릭 프로그래밍](#SS-GP)과 [컨셉](#SS-t-concepts)을 참고하라 +[제너릭 프로그래밍](./Templates.md#SS-GP)과 [컨셉](./Templates.md#SS-t-concepts)을 참고하라 ##### Enforcement @@ -669,9 +669,9 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 * 명시적인 오류 검사 및 처리는 종종 예외 처리만큼 많은 시간과 공간을 쓰기도 한다. * 간결한 코드는 종종 예외 처리를 포함하더라도 더 좋은 성능을 갖는다. (프로그램과 최적화를 통해 실행 경로를 단순화한다) -* 성능이 중요한 코드의 좋은 규칙은 오류 검사를 코드의 핵심 부분 바깥으로 옮기는 것이다 ([검사](#Rper-checking)). +* 성능이 중요한 코드의 좋은 규칙은 오류 검사를 코드의 핵심 부분 바깥으로 옮기는 것이다 ([검사](./Performance.md#Rper-checking)). * 장기적으로 보면 정돈된(regular) 코드가 더 잘 최적화된다. -* 성능에 대해 지적하기 전에는 항상 신중하게 [측정하라](#Rper-measure). +* 성능에 대해 지적하기 전에는 항상 신중하게 [측정하라](./Performance.md#Rper-measure). ##### See Also 사전 조건, 사후 조건의 위반 보고를 위한 [I.5](#Ri-pre) 및 [I.7](#Ri-post). @@ -714,12 +714,12 @@ C++11에 도입된 `std::chrono::duration` 타입은 지속 시간의 단위를 ##### Alternative -[소유권 전달](#Rr-smartptrparam)은 배타적 소유를 위한 `unique_ptr`와 공유를 위한 `shared_ptr` 같은 스마트 포인터를 사용하라. +[소유권 전달](./Resource.md#Rr-smartptrparam)은 배타적 소유를 위한 `unique_ptr`와 공유를 위한 `shared_ptr` 같은 스마트 포인터를 사용하라. 하지만 이는 개체 그 자체를 반환하는 것보다 덜 아름답고 덜 효율적이다. 오직 참조로 사용하도록 할때만 스마트 포인터를 사용하라. ABI 호환성 요구 사항 또는 리소스 부족으로 인해 오래된 코드를 수정할 수 없는 경우가 있다. -이 경우, [가이드라인 지원 라이브러리](#S-gsl)의 `owner`를 사용해 포인터의 소유권을 표시하라: +이 경우, [가이드라인 지원 라이브러리](./GSL.md#S-gsl)의 `owner`를 사용해 포인터의 소유권을 표시하라: ```c++ owner compute(args) // It is now clear that ownership is transferred @@ -743,9 +743,9 @@ ABI 호환성 요구 사항 또는 리소스 부족으로 인해 오래된 코 ##### See Also -* [인자 전달](#Rf-conventional) -* [스마트 포인터의 사용](#Rr-smartptrparam) -* [값 반환](#Rf-value-return) +* [인자 전달](./Functions.md#Rf-conventional) +* [스마트 포인터의 사용](./Resource.md#Rr-smartptrparam) +* [값 반환](./Functions.md#Rf-value-return) ##### Enforcement @@ -776,7 +776,7 @@ ABI 호환성 요구 사항 또는 리소스 부족으로 인해 오래된 코 ##### Note -`not_null`은 [가이드라인 지원 라이브러리](#S-gsl)에 정의되어 있다. +`not_null`은 [가이드라인 지원 라이브러리](./GSL.md#S-gsl)에 정의되어 있다. ##### Note @@ -861,7 +861,7 @@ ABI 호환성 요구 사항 또는 리소스 부족으로 인해 오래된 코 ##### Exception `zstring`과 `czstring`을 사용해 C-스타일의 `\0`로 끝나는 문자열을 나타내라. -하지만 이렇게 할때는 범위 오류가 발생하지 않도록 [GSL](#GSL)의 `string_span`를 사용하라. +하지만 이렇게 할때는 범위 오류가 발생하지 않도록 [GSL](./GSL.md#GSL)의 `string_span`를 사용하라. ##### Enforcement @@ -1193,8 +1193,8 @@ private 데이터는 클래스의 메모리 레이아웃에 영향을 주고 멤 istream& in = *inp; ``` -이는 [초기화되지 않은 변수를 피하라](#Res-always)는 규칙을 위반한다. -또한 [소유권을 무시](#Ri-raw)하며, [마법 상수를 피하라](#Res-magic)는 규칙에도 반한다. +이는 [초기화되지 않은 변수를 피하라](./Expr.md#Res-always)는 규칙을 위반한다. +또한 [소유권을 무시](#Ri-raw)하며, [마법 상수를 피하라](./Expr.md#Res-magic)는 규칙에도 반한다. 특히, 이 코드는 누군가 어딘가에 아래와 같은 코드를 작성해야 한다는 점을 기억해야만 한다. ```c++ diff --git a/sections/Introduction.md b/sections/Introduction.md index 7879133..ddf1a59 100644 --- a/sections/Introduction.md +++ b/sections/Introduction.md @@ -15,7 +15,7 @@ ## In.target: 대상 독자 -모든 C++ 프로그래머. 또한 [C를 생각 중인 프로그래머](#S-cpl). +모든 C++ 프로그래머. 또한 [C를 생각 중인 프로그래머](./CPL.md#S-cpl). ## In.aims: 목표 @@ -32,9 +32,9 @@ 여러분의 프로그램에 가이드라인에 나온 규칙을 적용한다면, 프로그램에 어떤 영향을 줄 지 충분히 고려해야 한다. -가이드라인은 "상위 집합의 하위 집합(Subset of superset)" ([Stroustrup05](#Stroustrup05)) 원리에 따라 구성되어 있다. +가이드라인은 "상위 집합의 하위 집합(Subset of superset)" ([Stroustrup05](./Bibliography.md#Stroustrup05)) 원리에 따라 구성되어 있다. 우리는 신뢰성, 안정성, 성능 등을 고려해 단순히 C++의 한 부분 집합을 정의하지 않는다. -대신, 몇 가지 간단한 "확장" ([라이브러리 구성 요소](#S-gsl))을 사용하길 강력히 권고한다. +대신, 몇 가지 간단한 "확장" ([가이드라인 지원 라이브러리](./GSL.md#S-gsl))을 사용하길 강력히 권고한다. 이를 통해 오류가 발생하기 쉬운 C++ 기능들의 대부분을 제거할 수 있다. 규칙들은 정적 타입 안정성과 리소스 안정성에 주안점을 두고 있다. @@ -52,7 +52,7 @@ 이처럼 특화된 개발 분야에만 적용 할 수 있는 규칙들은 핵심 가이드라인의 부록에 담았다. 어셈블리 코드와 같이 저수준의 프로그래밍 방식을 고수하기 보다는 핵심 기능을 구현하고 있는 소규모의 라이브러리를 만들고 사용하기 바란다. -규칙들은 [점진적으로 적용](#S-modernizing)해 볼 수 있다. +규칙들은 [점진적으로 적용](./appendix/Modernizing.md#S-modernizing)해 볼 수 있다. 일부 규칙들은 안정성을 높이기 위해 다양한 방법들을 설명하고 있으며, 또 다른 규칙들은 문제 발생 가능성을 낮추는 방법을 설명하고 있다. 혹은 이 둘을 모두 고려해 만들어진 규칙들도 있다. 사고를 예방하기 위한 가이드라인이 때로는 합법적인(legal) C++에 반대되기도 한다. @@ -71,11 +71,11 @@ 즉, 규칙이 만들어진 이유를 설명하고, 만약 규칙을 따르지 않았을 때 어떤 문제가 발생할 수 있고, 그 문제를 어떻게 해결할 수 있는지를 알려주기 위해서다. 이 가이드라인은 C++ 튜토리얼을 대체할 용도로 작성된 것이 아니다. -개발자의 수준에 부합하는 튜토리얼이 필요하다면, [참고 문헌](#S-references)을 참조하기 바란다. +개발자의 수준에 부합하는 튜토리얼이 필요하다면, [참고 문헌](./References.md#S-references)을 참조하기 바란다. 이 문서는 기존의 C++ 코드를 모던 C++ 코드로 변환하는 방법에 대해서 다루고 있는 것도 아니다. 다만, 새로운 C++ 코드에 대한 논리 정연한 생각들을 구체적으로 설명한다. -따라서 기존 코드를 모던하게, 젊고 활기차게, 업그레이드 하고 싶다면 [모던 C++ 코드](#S-modernizing)를 참조하기 바란다. +따라서 기존 코드를 모던하게, 젊고 활기차게, 업그레이드 하고 싶다면 [모던 C++ 코드](./appendix/Modernizing.md#S-modernizing)를 참조하기 바란다. 중요한 것은 이 문서에서 다루고 있는 규칙들을 점진적으로 적용할 수 있다는 점이다. 엄청난 양의 코드를 단번에 바꿀 수는 없는 노릇이다. 이 가이드라인이 언어의 기술 세부 사항을 완벽하게, 또는 정확하게 설명하지는 않는다. @@ -117,12 +117,12 @@ 바라건대 모든 규칙들을 적용하는 것이 좋다고 생각한다. 그렇게 해야만 최고의 이득을 본다고 생각하기 때문이다. 이는 꽤나 심각한 딜레마가 아닐 수 없는데, 우리는 이러한 딜레마의 해결책이 툴을 개발하는 것이라고 생각했다. -각각의 규칙들은 적용 방법을 설명하고 있는 **적용** 단락을 갖고 있는데, +각각의 규칙들은 적용 방법을 설명하고 있는 **Enforcement** 단락을 갖고 있는데, 코드 리뷰, 정적 분석, 컴파일러, 런타임 체크 등의 방법을 나열하고 있다. 어떤 방식이든 우리는 "기계적"이며(사람은 느리기도 하고, 쉽게 지루해 할 수 있으므로) 일관된 방법으로 개별 규칙들이 적용되기를 원했다. 이런 이유로 런타임 체크는 다른 대안이 없을 경우에 한해서만 언급했다. 이 같은 내용들을 여기저기에 흩어놓기 보다는 사용자가 원할 경우 쉽게 찾을 수 있도록 하고 싶었기에, -(**적용** 단락 내에) 적절한 위치라고 생각되는 곳에 연관된 규칙들을 "프로필"이라는 이름으로 나열해 두었다. +(**Enforcement** 단락 내에) 적절한 위치라고 생각되는 곳에 연관된 규칙들을 "프로필"이라는 이름으로 나열해 두었다. 하나의 규칙은 여러 프로필에 속할 수 있으며, 어떤 프로필에도 속하지 않은 규칙들도 있다. 자주 사용되는 프로필 몇 가지를 먼저 살펴보자. @@ -136,9 +136,11 @@ 가이드라인의 규칙들을 구현한 툴에서는 명시적으로 규칙을 무시하는 다음과 같은 문법을 지원하기를 바란다: +```c++ [[gsl::suppress(tag)]] +``` -여기서 "tag"는 HTML anchor의 이름으로, 가이드라인 내에서 규칙이 있는 지점을 의미한다. (가령, [C.134](#Rh-public) 규칙의 경우, Anchor 값은 "Rh-public"이다. ) +여기서 "tag"는 HTML anchor의 이름으로, 가이드라인 내에서 규칙이 있는 지점을 의미한다. (가령, [C.134](./Class.md#Rh-public) 규칙의 경우, Anchor 값은 "Rh-public"이다. ) ## In.struct: 문서의 구조 @@ -161,48 +163,48 @@ 일부 규칙들은 기계적으로 확인하기에 어려울 수 있으나 전문적인 프로그래머라면 손쉽게 위반 여부를 발견할 수 있다. "기계적인" 도구들이 그런 전문 프로그래머 처럼 지적할 수 있도록 발전하기를 희망한다. 또, 규칙들이 시간이 지날수록 더 정확하고 검사가 가능하도록 발전하도록 할 것이다. 각 규칙들이 가능한 단순하게 유지되길 바란다. 적용 가능한 모든 대안과 특별한 예외사항까지 모두 언급하기를 바라지는 않는다. -이러한 정보는 **대안** 단락과 [토론](#S-discussion) 절에서 찾을 수 있다. +이러한 정보는 **대안** 단락과 [토론](./appendix/Discussion.md#S-discussion) 절에서 찾을 수 있다. 규칙을 이해할 수 없거나 동의하지 않는다면, **논의**를 살펴보기 바란다. 또한, 논의가 없거나 불완전하다고 생각된다면 Issue에 여러분이 염려하는 부분과 가능하다면 관련 PR에 대한 설명을 적어주기 바란다. 이 문서는 언어어 대한 매뉴얼이 아니다. 따라서 기술적인 세부 사항을 자세히 다루기보다는 기존에 작성된 코드에 대한 가이드로써의 역할을 했으면 한다. -도움이 되는 정보의 출처는 [참고 문헌](#S-references)에서 찾을 수 있다. +도움이 되는 정보의 출처는 [참고 문헌](./References.md#S-references)에서 찾을 수 있다. ## In.sec: 주요 목차 * [In(Introduction): 소개](#S-introduction) -* [P(Philosophy): 철학](#S-philosophy) -* [I(Interfaces): 인터페이스](#S-interfaces) -* [F(Functions): 함수](#S-functions) -* [C(Classes and class hierarchies): 클래스와 클래스 계층 구조](#S-class) -* [Enum(Enumerations): 열거형](#S-enum) -* [R(Resource management): 리소스 관리](#S-resource) -* [ES(Expressions and statements): 표현식과 문장](#S-expr) -* [Per(Performance): 성능](#S-performance) -* [CP(Concurrency): 동시성](#S-concurrency) -* [E(Error handling): 오류 처리](#S-errors) -* [Con(Constants and immutability): 상수와 불변성](#S-const) -* [T(Templates and generic programming): 템플릿과 제너릭 프로그래밍](#S-templates) -* [CPL(C-style programming): C 스타일 프로그래밍](#S-cpl) -* [SF(Source files): 소스 파일](#S-source) -* [SL(The Standard library): 표준 라이브러리](#S-stdlib) +* [P(Philosophy): 철학](./Philosophy.md) +* [I(Interfaces): 인터페이스](./Interfaces.md) +* [F(Functions): 함수](./Functions.md) +* [C(Classes and class hierarchies): 클래스와 클래스 계층 구조](./Class.md) +* [Enum(Enumerations): 열거형](./Enum.md) +* [R(Resource management): 리소스 관리](./Resource.md) +* [ES(Expressions and statements): 표현식과 구문](./Expr.md) +* [Per(Performance): 성능](./Performance.md) +* [CP(Concurrency): 동시성](./Concurrency.md) +* [E(Error handling): 오류 처리](./Errors.md) +* [Con(Constants and immutability): 상수와 불변성](./Const.md) +* [T(Templates and generic programming): 템플릿과 제너릭 프로그래밍](./Templates.md) +* [CPL(C-style programming): C 스타일 프로그래밍](./CPL.md) +* [SF(Source files): 소스 파일](./Source.md) +* [SL(The Standard library): 표준 라이브러리](./SL.md) 참고할 만한 내용: -* [A(Architectural Ideas): 구조적 아이디어](#S-A) -* [NR(Non-Rules and myths): 규칙이 아닌 미신](#S-not) -* [RF(References): 참고 문헌](#S-references) -* [Pro(Profiles): 프로파일](#S-profile) -* [GSL(Guideline support library): 가이드라인 지원 라이브러리](#S-gsl) -* [NL(Naming and layout): 이름 명명 규칙과 레이아웃](#S-naming) -* [FAQ(Answers to frequently asked questions): 자주 묻는 질문에 대한 대답](#S-faq) -* [부록 A: 라이브러리](#S-libraries) -* [부록 B: 모던 C++ 스타일로 코딩하기](#S-modernizing) -* [부록 C: 토론](#S-discussion) -* [부록 D: 유용한 도구](#S-tools) -* [용어 설명](#S-glossary) -* [To-do(Unclassified proto-rules): 미분류 규칙](#S-unclassified) +* [A(Architectural Ideas): 프로그램 구조 관련 아이디어](Architecture.md) +* [NR(Non-Rules and myths): 규칙이 아닌 미신](./Not.md) +* [RF(References): 참고 문헌](./References.md) +* [Pro(Profiles): 프로파일](./Profile.md) +* [GSL(Guideline support library): 가이드라인 지원 라이브러리](./GSL.md) +* [NL(Naming and layout): 이름 명명 규칙과 레이아웃](./Naming.md) +* [FAQ(Answers to frequently asked questions): 자주 묻는 질문에 대한 대답](./FAQ.md) +* [부록 A: 라이브러리](./appendix/Libraries.md) +* [부록 B: 모던 C++ 스타일로 코딩하기](./appendix/Modernizing.md) +* [부록 C: 토론](./appendix/Discussion.md) +* [부록 D: 유용한 도구](./appendix/Tools.md) +* [용어 설명](./Glossary.md) +* [To-do(Unclassified proto-rules): 미분류 규칙](./Unclassified.md) 각 부분들은 서로 연관되어 있다. From 57c59909f43b3b109137dda74933ff8798ef79df Mon Sep 17 00:00:00 2001 From: luncliff Date: Wed, 3 Jul 2019 00:50:29 +0900 Subject: [PATCH 3/7] broken links: Class --- sections/Class.md | 59 ++++++++++++++++++++------------------ sections/Profile.md | 24 ++++++++-------- sections/ReadMe.md | 70 ++++++++++++++++++++++----------------------- 3 files changed, 78 insertions(+), 75 deletions(-) diff --git a/sections/Class.md b/sections/Class.md index 9ff98be..fbd6801 100644 --- a/sections/Class.md +++ b/sections/Class.md @@ -283,7 +283,7 @@ private 데이터가 public data와 멀리 떨어져 숨어있고, 클래스 선 ##### Note -클래스 인터페이스를 먼저 배치하라. [NL.16을 참고하라](#Rl-order) +클래스 인터페이스를 먼저 배치하라. [NL.16을 참고하라](./Naming.md#Rl-order) ##### Enforcement @@ -910,7 +910,7 @@ C++ 에서는 기본적인 의미를 가진 연산들을 제공한다. ##### Example -포인터 멤버는 리소스일 것이다. [`T*`는 리소스가 아니어야 한다](#Rr-ptr), 이는 오래된 코드에서는 일반적이다. +포인터 멤버는 리소스일 것이다. [`T*`는 리소스가 아니어야 한다](./Resource.md#Rr-ptr), 이는 오래된 코드에서는 일반적이다. 가능한 `T*`를 소유자라고 고려하고, 의심해보라. ```c++ @@ -995,7 +995,7 @@ C++ 에서는 기본적인 의미를 가진 연산들을 제공한다. ##### Discussion -[토론](#Sd-dtor)을 함께 읽어보라. +[토론](./Discussion.md#Sd-dtor)을 함께 읽어보라. ##### Example, bad @@ -1080,7 +1080,7 @@ protected virtual 소멸자를 원하지 않는 경우를 상상해볼 수 있 이것은 정말 현실적인 문제가 될 수 있다: 예를 들면, 닫지 않은 소켓은 어떤가? 소멸자를 작성하는 사람은 왜 소멸자가 호출되고 예외를 던짐으로써 "동작을 거부하는 것"을 할 수 없는지 모른다. -[토론](#Sd-dtor)을 함께보라. +[토론](./Discussion.md#Sd-dtor)을 함께보라. 문제를 악화시키는 것은, 많은 "close/release" 연산이 재시도할 수 없게 되어있는 것이다. 가능하다면, close/failure에 대한 실패를 근본적인 디자인 오류로 간주하고 종료시켜라. @@ -1255,7 +1255,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 ##### Note 생성자가 유효한 개체를 만들기 위해 자원을 얻는다면, 리소스는 [소멸자에 의해 해제](#Rc-release)되어야 한다. -생성자에서 자원을 얻고 소멸자에서 자원을 해제하는 것을 [RAII](Rr-raii) ("Resource Acquisitions Is Initialization") 라고 한다. +생성자에서 자원을 얻고 소멸자에서 자원을 해제하는 것을 [RAII](./Resource.md#Rr-raii) ("Resource Acquisitions Is Initialization") 라고 한다. ### C.42: 생성자가 유효한 개체를 생성하지 못한다면, 예외를 던지도록 하라 @@ -1345,7 +1345,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 사람들이 생성자에서 초기화를 수행하지 않고 `init()`함수를 사용해온 이유 중 하나는 코드의 중복을 막기 위함이었다. [대리 생성자](#Rc-delegating)와 [기본 멤버 초기화](#Rc-in-class-initializer)가 이런 작업을 더 잘 해낼 수 있다. -또 다른 이유로는 개체가 필요할 때까지 초기화를 지연시키는 것이다; 이러한 해법은 보통 [변수가 적절하게 초기화되기 전까지는 해당 변수를 선언하지 않는 것이다](#Res-init). +또 다른 이유로는 개체가 필요할 때까지 초기화를 지연시키는 것이다; 이러한 해법은 보통 [변수가 적절하게 초기화되기 전까지는 해당 변수를 선언하지 않는 것이다](./Expr.md#Res-init). ##### Enforcement @@ -1357,7 +1357,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 많은 언어나 라이브러리들이 기본 생성자에 의존하고 있다. 예를 들면, `T a[10]` 나 `std::vector v(10)` 는 기본 생성자들이 각 요소를 초기화 한다. -기본 생성자는 보통 복사 가능한 타입이 적합한 [이동 된 상태](#???)를 정의하기 쉽도록 한다. +기본 생성자는 보통 복사 가능한 타입이 적합한 이동 된 상태를 정의하기 쉽도록 한다. ##### Note @@ -1389,7 +1389,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 class Date { public: Date(int dd, int mm, int yyyy); - Date() = default; // [See also](#Rc-default) + Date() = default; // C.45: 멤버를 초기화 하기만 하는 기본 생성자는 정의하지 마라 // ... private: int dd = 1; @@ -1488,7 +1488,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 * 클래스가 기본 생성자 없이 복사 가능한 경우를 지적한다 * 클래스가 복사를 지원하지 않으면서 동등 비교(`==`)가 가능하면 지적한다 -### C.44: 기본 생성자는 가능한 단순하고 예외를 던지지 않도록 하라 +### C.44: 기본 생성자는 가능한 단순하고 예외를 던지지 않도록 하라 ##### Reason @@ -1644,7 +1644,8 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 (단순) 멤버 초기화 리스트는 선언과 같은 순서로 진행되어야 한다. ##### See also -[Discussion](#Sd-order) + +[Discussion](./appendix/Discussion.md#Sd-order) ### C.48: 상수 초기화는 가능한 클래스 내(in-class) 멤버 초기화를 사용하라 @@ -1805,7 +1806,8 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 전통적인 팩토리 함수들은 스택이나 인접 개체보다는 자유 저장소에 생성한다. ##### See also -[Discussion](#Sd-factory) + +[Discussion](./appendix/Discussion.md#Sd-factory) ### C.51: 클래스의 모든 생성자들을 위한 일반적인 동작을 표현할 때는 대리 생성자를 사용하라 @@ -1908,7 +1910,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 ##### Reason -이렇게 하는 것이 간단하고 효율적이다. r-value를 위해 최적화하길 원한다면, `&&`를 받는 대입 연산을 오버로드하여 제공하라. ([F.18](#Rf-consume)를 보라) +이렇게 하는 것이 간단하고 효율적이다. r-value를 위해 최적화하길 원한다면, `&&`를 받는 대입 연산을 오버로드하여 제공하라. ([F.18](./Functions.md#Rf-consume)를 보라) ##### Example @@ -1935,7 +1937,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 ##### Note -`swap`함수의 구현은 [강한 예외 안전성 보장](#Abrahams01)을 가능하게 한다. +`swap`함수의 구현은 [강한 예외 안전성 보장](./Bibliography.md#Abrahams01)을 가능하게 한다. ##### Example @@ -1969,7 +1971,7 @@ C++11 초기화 리스트 규칙은 많은 생성자의 필요성을 제거한 } ``` -대상 원소들에 직접 쓰기 연산을 함으로써, `swap`기법이 제공하는 강한 예외 보장 대신 [기본적인 예외 보장](#Abrahams01)만 얻게 될 것이다. +대상 원소들에 직접 쓰기 연산을 함으로써, `swap`기법이 제공하는 강한 예외 보장 대신 [기본적인 예외 보장](./Bibliography.md#Abrahams01)만 얻게 될 것이다. [자기 대입](#Rc-copy-self)에 주의하라. ##### Alternatives @@ -2539,7 +2541,7 @@ delete된 함수들이 public이라는 점에 주목하라 ##### Reason `swap`함수는 개체 대입을 구현할 때 원활하게 개체를 이동하는 것에서, 에러가 발생하지 않는 것을 보장하는 함수를 제공하는 것까지 몇몇 함수들(idioms)을 구현하는데 유용하다. -swap함수을 이용해서 복사 대입을 구현하는 것을 고려하라. [소멸자, 자원 해제, 그리고 swap은 실패해선 안된다]("#Re-never-fail). +swap함수을 이용해서 복사 대입을 구현하는 것을 고려하라. [소멸자, 자원 해제, 그리고 swap은 실패해선 안된다](#Re-never-fail). ##### Example, good @@ -2762,13 +2764,14 @@ swap함수을 이용해서 복사 대입을 구현하는 것을 고려하라. [ * [C.109: 리소스 핸들이 포인터 의미구조를 따를 경우에는, `*` 과 `->` 연산자를 제공하라](#rcon-ptr) ##### See also -[Resources](#S-resource) + +[R: 자원 관리](./Resource.md#S-resource) ### C.100: 컨테이너를 정의할때는 STL을 따르라 ##### Reason -C++ 프로그래머들에게 STL 컨테이너는 친숙하고 근본적으로 완전한(fundamentally sound) 설계를 가지고 있다. +C++ 프로그래머들에게 STL 컨테이너는 친숙하고 기본적으로 적절한(fundamentally sound) 설계를 가지고 있다. ##### Note @@ -2923,14 +2926,14 @@ C++ 프로그래머들에게 STL 컨테이너는 친숙하고 근본적으로 함수 개체는 `()`를 오버로드해 호출을 지원하는 개체를 의미한다. 람다 표현식(줄여서 "람다"라고도 한다)은 함수 개체를 생성하도록 하는 표기를 의미한다. -함수 개체는 가능한 복사 비용을 발생시키지 않아야 한다 (또 그렇기에 [값에 의한 전달](#Rf-in)이 사용된다). +함수 개체는 가능한 복사 비용을 발생시키지 않아야 한다 (또 그렇기에 [값에 의한 전달](./Functions.md#Rf-in)이 사용된다). 요약: -* [F.50: 함수를 사용할 수 없다면 람다를 사용하라 (지역 변수를 복사하거나, 지역적으로 사용되는 함수를 작성하는 경우)](#Rf-capture-vs-overload) -* [F.52: 지역적으로 사용되거나 알고리즘에 전달된다면 람다 캡쳐로는 참조를 선호하라](#Rf-reference-capture) -* [F.53: 반환되거나, 외부에 저장되거나, 다른 스레드로 전달하는 경우처럼 비 지역적으로 사용된다면 람다의 참조 캡쳐를 지양하라](#Rf-value-capture) -* [ES.28: 복잡한 초기화에는, 특히 상수 변수들의 초기화에는 람다를 사용하라](#Res-lambda-init) +* [F.50: 함수를 사용할 수 없다면 람다를 사용하라 (지역 변수를 복사하거나, 지역적으로 사용되는 함수를 작성하는 경우)](./Functions.md#Rf-capture-vs-overload) +* [F.52: 지역적으로 사용되거나 알고리즘에 전달된다면 람다 캡쳐로는 참조를 선호하라](./Functions.md#Rf-reference-capture) +* [F.53: 반환되거나, 외부에 저장되거나, 다른 스레드로 전달하는 경우처럼 비 지역적으로 사용된다면 람다의 참조 캡쳐를 지양하라](./Functions.md#Rf-value-capture) +* [ES.28: 복잡한 초기화에는, 특히 상수 변수들의 초기화에는 람다를 사용하라](./Expr.md#Res-lambda-init) ## C.hier: 클래스 계층 구조 (OOP) @@ -3265,7 +3268,7 @@ C++ 프로그래머들에게 STL 컨테이너는 친숙하고 근본적으로 * 인터페이스 상속은 사용자 코드를 구현과 분리하기 위한 것이다. 하위 클래스에서 상위 클래스를 사용하는 코드에 영향을 미치지 않으면서 코드를 더하거나 변경하는데 사용된다 * 구현 상속은 상속을 사용해 새로운 구현내용을 하위 구현체들이 사용할 수 있도록하는 것이다 (보통 "programming by difference"라고 불린다). -순수한 인터페이스 클래스는 쉽게말해 순수 가상함수들의 집합이라고 할 수 있다; [I.25](#Ri-abstract)를 참고하라. +순수한 인터페이스 클래스는 쉽게말해 순수 가상함수들의 집합이라고 할 수 있다; [I.25](./Interfaces.md#Ri-abstract)를 참고하라. 초창기의 개체지향 프로그래밍에서는 (1980년도와 1990년도), 구현 상속과 인터페이스 상속이 혼재되어 있었고 그런 인습이 아직도 남아있다. 오래된 코드나 교육자료에서는 흔히 볼 수 있다. @@ -3473,7 +3476,7 @@ C++ 프로그래머들에게 STL 컨테이너는 친숙하고 근본적으로 ##### Note -인터페이스와 구현을 분리하기 위한 또 다른 (관련된) 방법은 [Pimpl](#Ri-pimpl)이다. +인터페이스와 구현을 분리하기 위한 또 다른 (관련된) 방법은 [Pimpl](./Interfaces.md#Ri-pimpl)이다. ##### Note @@ -3513,7 +3516,7 @@ C++ 프로그래머들에게 STL 컨테이너는 친숙하고 근본적으로 }; ``` -보편적인 경우, 소유권을 표현하기 위해 스마트 포인터를 사용하는 것이 권장된다.([R.20](#Rr-owner) 참고). 하지만, 언어 규칙으로 인해, 공변적인 반환타입은 스마트 포인터가 될 수 없다: `D::clone`은 `unique_ptr`을 반환할 수 없는 반면 `B::clone`는 `unique_ptr`를 반환할 수 있다. 이로 인해, 모든 재정의에서 항상 `unique_ptr` 혹은 [Guidelines Support Library](#SS-views)의 `owner<>`를 반환할 수 밖에 없다. +보편적인 경우, 소유권을 표현하기 위해 스마트 포인터를 사용하는 것이 권장된다.([R.20](./Resource.md#Rr-owner) 참고). 하지만, 언어 규칙으로 인해, 공변적인 반환타입은 스마트 포인터가 될 수 없다: `D::clone`은 `unique_ptr`을 반환할 수 없는 반면 `B::clone`는 `unique_ptr`를 반환할 수 있다. 이로 인해, 모든 재정의에서 항상 `unique_ptr` 혹은 [Guidelines Support Library](./GSL.md#SS-views)의 `owner<>`를 반환할 수 밖에 없다. ### C.131: 자잘한 getter와 setter를 사용하지 말아라 @@ -4008,7 +4011,7 @@ Both `d`s are sliced. 다른 모든 캐스팅처럼, `dynamic_cast`는 너무 자주 사용된다. [캐스팅 보다는 가상 함수들을 사용하라](#Rh-use-virtual). -가능한 한 클래스 계층을 탐색하는 것보다 [정적 다형성](#???)을 선호하라. 이렇게 하면 실행시간 결정이 필요없다. 그리고 충분히 편리하다. +가능한 한 클래스 계층을 탐색하는 것보다 [정적 다형성(링크 없음))](#???)을 선호하라. 이렇게 하면 실행시간 결정이 필요없다. 그리고 충분히 편리하다. ##### Note @@ -4063,7 +4066,7 @@ RTTI를 직접 구현하고자 한다면, 주의하라. 당신만의 특별한 `dynamic_cast`를 만들수도 있을 것이다. 그러니, `dynamic_cast`가 정말로 당신이 생각하는 것 만큼 느리다는 것을 확실히하라. (근거 없는 루머들이 꽤 있다.) 그리고 `dynamic_cast`의 사용이 정말로 성능에 치명적이라는 것 또한 확인하라. 이는 `dynamic_cast`의 현재 구현이 불필요하게 느린 경우에 대한 것이다. -예를 들어, 적절한 조건 하에서는, `dynamic_cast`를 [상수시간으로 빠르게](http://www.stroustrup.com/fast_dynamic_casting.pdf) 수행할 수 있다. 하지만, 최적화를 위해 노력할 가치가 있다는데 모두가 동의하지 않으면 호환성은 코드 변경을 어렵게 한다. +예를 들어, 적절한 조건 하에서는, `dynamic_cast`를 [O(1)시간 내로 수행](http://www.stroustrup.com/fast_dynamic_casting.pdf)할 수 있다. 하지만, 최적화를 위해 노력할 가치가 있다는데 모두가 동의하지 않으면 호환성은 코드 변경을 어렵게 한다. 매우 드물게, `dynamic_cast`의 오버헤드가 문제가 된다면, 하향 캐스팅이 성공한다고 정적으로 보장되는 다른 방법을 쓸 수도 있다 (예를 들어 Curiously Recurring Template Pattern을 주의해서 쓰는 방법처럼). 가상 상속을 사용하지 않는다면, 확실한 주석과 함께 `static_cast`에 의존하거나 시스템이 정확성을 검증할 수 없기 때문에 유지보수에 사람이 필요하다는 조항을 작성하라. @@ -4083,7 +4086,7 @@ RTTI를 직접 구현하고자 한다면, 주의하라. ##### Enforcement * 모든 하위 타입으로의 `static_cast`를 지적하라. `static_cast`를 수행하는 C 스타일 변환도 포함하라 -* 이 규칙은 [타입 안전성](#Pro-type-downcast) 규칙들의 일부이다 +* 이 규칙은 [타입 안전성](./Profile.md#Pro-type-downcast) 규칙들의 일부이다 ### C.147: 필요한 클래스를 찾지 못한 경우가 오류에 해당하는 경우 `dynamic_cast`를 참조 타입에 사용하라 diff --git a/sections/Profile.md b/sections/Profile.md index beb221f..8686041 100644 --- a/sections/Profile.md +++ b/sections/Profile.md @@ -68,18 +68,18 @@ 타입 안전성 프로필 요약: -* Type.1: [Avoid casts](#Res-casts): - * Don't use `reinterpret_cast`; A strict version of [Avoid casts](#Res-casts) and [prefer named casts](#Res-casts-named) - * Don't use `static_cast` for arithmetic types; A strict version of [Avoid casts](#Res-casts) and [prefer named casts](#Res-casts-named). - * Don't cast between pointer types where the source type and the target type are the same; A strict version of [Avoid casts](#Res-casts). - * Don't cast between pointer types when the conversion could be implicit; A strict version of [Avoid casts](#Res-casts). -* Type.2: Don't use `static_cast` to downcast: [Use `dynamic_cast` instead](#Rh-dynamic_cast). -* Type.3: Don't use `const_cast` to cast away `const` (i.e., at all): [Don't cast away const](#Res-casts-const). -* Type.4: Don't use C-style `(T)expression` or functional `T(expression)` casts: Prefer [construction](#Res-construct) or [named casts](#Res-cast-named). -* Type.5: Don't use a variable before it has been initialized: [always initialize](#Res-always). -* Type.6: Always initialize a member variable: [always initialize](#Res-always), possibly using [default constructors](#Rc-default0) or [default member initializers](#Rc-in-class-initializers). -* Type.7: Avoid naked union: [Use `variant` instead](#Ru-naked). -* Type.8: Avoid varargs: [Don't use `va_arg` arguments](#F-varargs). +* Type.1: [Avoid casts](./Expr.md#Res-casts): + * Don't use `reinterpret_cast`; A strict version of [Avoid casts](#Res-casts) and [prefer named casts](./Expr.md#Res-casts-named) + * Don't use `static_cast` for arithmetic types; A strict version of [Avoid casts](./Expr.md#Res-casts) and [prefer named casts](./Expr.md#Res-casts-named). + * Don't cast between pointer types where the source type and the target type are the same; A strict version of [Avoid casts](./Expr.md#Res-casts). + * Don't cast between pointer types when the conversion could be implicit; A strict version of [Avoid casts](./Expr.md#Res-casts). +* Type.2: Don't use `static_cast` to downcast: [Use `dynamic_cast` instead](./Class.md#Rh-dynamic_cast). +* Type.3: Don't use `const_cast` to cast away `const` (i.e., at all): [Don't cast away const](./Expr.md#Res-casts-const). +* Type.4: Don't use C-style `(T)expression` or functional `T(expression)` casts: Prefer [construction](./Expr.md#Res-construct) or [named casts](./Expr.md#Res-cast-named). +* Type.5: Don't use a variable before it has been initialized: [always initialize](./Expr.md#Res-always). +* Type.6: Always initialize a member variable: [always initialize](./Expr.md#Res-always), possibly using [default constructors](./Class.md#Rc-default0) or [default member initializers](./Class.md#Rc-in-class-initializers). +* Type.7: Avoid naked union: [Use `variant` instead](./Class.md#Ru-naked). +* Type.8: Avoid varargs: [Don't use `va_arg` arguments](./Functions.md#F-varargs). ##### Impact diff --git a/sections/ReadMe.md b/sections/ReadMe.md index 8b7cfa7..a00c9b8 100644 --- a/sections/ReadMe.md +++ b/sections/ReadMe.md @@ -59,49 +59,49 @@ 구체적인 언어 기능과 관련된 규칙들: * assignment - * [regular types](#Rc-regular) - * [prefer initialization](#Rc-initialize) - * [copy](#Rc-copy-semantic) - * [move](#Rc-move-semantic) - * [other operations](#Rc-matched) - * [default](#Rc-eqdefault) + * [regular types](./Class.md#Rc-regular) + * [prefer initialization](./Class.md#Rc-initialize) + * [copy](./Class.md#Rc-copy-semantic) + * [move](./Class.md#Rc-move-semantic) + * [other operations](./Class.md#Rc-matched) + * [default](./Class.md#Rc-eqdefault) * `class` - * [data](#Rc-org) - * [invariant](#Rc-struct) - * [members](#Rc-member) - * [helpers](#Rc-helper) - * [concrete types](#SS-concrete) - * [ctors, =, and dtors](#S-ctor) - * [hierarchy](#SS-hier) - * [operators](#SS-overload) + * [data](./Class.md#Rc-org) + * [invariant](./Class.md#Rc-struct) + * [members](./Class.md#Rc-member) + * [helpers](./Class.md#Rc-helper) + * [concrete types](./Class.md#SS-concrete) + * [ctors, =, and dtors](./Class.md#S-ctor) + * [hierarchy](./Class.md#SS-hier) + * [operators](./Class.md#SS-overload) * `concept`: * [rules](#SS-concepts) * [in generic programming](#Rt-raise) * [template arguments](#Rt-concepts) * [semantics](#Rt-low) * constructor: - * [invariant](#Rc-struct) - * [establish invariant](#Rc-ctor) - * [`throw`](#Rc-throw) - * [default](#Rc-default0) - * [not needed](#Rc-default) - * [`explicit`](#Rc-explicit) - * [delegating](#Rc-delegating) - * [`virtual`](#Rc-ctor-virtual) + * [invariant](./Class.md#Rc-struct) + * [establish invariant](./Class.md#Rc-ctor) + * [`throw`](./Class.md#Rc-throw) + * [default](./Class.md#Rc-default0) + * [not needed](./Class.md#Rc-default) + * [`explicit`](./Class.md#Rc-explicit) + * [delegating](./Class.md#Rc-delegating) + * [`virtual`](./Class.md#Rc-ctor-virtual) * derived `class`: - * [when to use](#Rh-domain) - * [as interface](#Rh-abstract) - * [destructors](#Rh-dtor) - * [copy](#Rh-copy) - * [getters and setters](#Rh-get) - * [multiple inheritance](#Rh-mi-interface) - * [overloading](#Rh-using) - * [slicing](#Rc-copy-virtual) - * [`dynamic_cast`](#Rh-dynamic_cast) + * [when to use](./Class.md#Rh-domain) + * [as interface](./Class.md#Rh-abstract) + * [destructors](./Class.md#Rh-dtor) + * [copy](./Class.md#Rh-copy) + * [getters and setters](./Class.md#Rh-get) + * [multiple inheritance](./Class.md#Rh-mi-interface) + * [overloading](./Class.md#Rh-using) + * [slicing](./Class.md#Rc-copy-virtual) + * [`dynamic_cast`](./Class.md#Rh-dynamic_cast) * destructor: - * [and constructors](#Rc-matched) - * [when needed?](#Rc-dtor) - * [may not fail](#Rc-dtor-fail) + * [and constructors](./Class.md#Rc-matched) + * [when needed?](./Class.md#Rc-dtor) + * [may not fail](./Class.md#Rc-dtor-fail) * exception: * [errors](#S-errors) * [`throw`](#Re-throw) @@ -139,7 +139,7 @@ * [when to use](#SS-lambdas) * operator: * [conventional](#Ro-conventional) - * [avoid conversion operators](#Ro-conversion) + * [avoid conversion operators](./Class.md#Ro-conversion) * [lambdas](#Ro-lambda) * `public`, `private`, and `protected`: * [information hiding](#Rc-private) From d3f5d13dac21b202a0b7893e50605998a0fbadc7 Mon Sep 17 00:00:00 2001 From: luncliff Date: Wed, 3 Jul 2019 01:52:12 +0900 Subject: [PATCH 4/7] translate: SF 7 ~ 22 --- sections/Source.md | 102 ++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 43 deletions(-) diff --git a/sections/Source.md b/sections/Source.md index 6fa4da1..c743fd4 100644 --- a/sections/Source.md +++ b/sections/Source.md @@ -293,12 +293,13 @@ and M functions each containing a `using namespace X`with N lines of code in tot Flag multiple `using namespace` directives for different namespaces in a single source file. -### SF.7: Don't write `using namespace` at global scope in a header file +### SF.7: 헤더파일에서는 전체 유효범위(global scope)에 주는 `using namespace`를 작성하지 마라 ##### Reason -헤더 파일에 `using` 지시자를 사용하는 경우 `#include`를 사용하는 쪽에서 대체 구현을 효과적으로 구분할 수 있는 방안을 없애버린다. -It also makes `#include`d headers order-dependent as they may have different meaning when included in different orders. +헤더 파일에 `using` 지시자를 사용하는 경우 `#include`를 사용하는 쪽에서 다른 구현을 효과적으로 구분할 수 있는 방안을 없애버린다. +동시에 그 헤더가 `#include`되는 순서를 신경쓰도록 만든다(order-dependent). +이는 헤더의 순서가 바뀌면 의미가 달라지는것과 같다. ##### Example @@ -321,15 +322,19 @@ It also makes `#include`d headers order-dependent as they may have different mea Flag `using namespace` at global scope in a header file. -### SF.8: Use `#include` guards for all `.h` files +### SF.8: 모든 `.h`파일에서 `#include` 가드(guard)를 사용하라 + +> 역주: +> `#include` guard(보호 문구)는 어떤 헤더 파일이 여러차례 include 되었을 때 +> redefinition이 발생하지 않도록 +> Macro를 사용해 오직 처음 include할때만 그 내용이 활성화 되도록하는 트릭(Trick)을 말합니다 ##### Reason 파일이 여러 번 `#include`되는 것을 방지한다. -In order to avoid include guard collisions, do not just name the guard after the filename. -Be sure to also include a key and good differentiator, such as the name of library or component -the header file is part of. +가드의 이름이 충돌하는 것을 막기 위해, 단순히 파일의 이름을 따라서 가드들의 이름을 지어서는 안된다. +가드의 이름에 헤더파일이 담당하는 라이브러리 혹은 컴포넌트의 이름과 같은 핵심과 차별성(a key and good differentiator)이 담기게 하라. ##### Example @@ -337,26 +342,30 @@ the header file is part of. // file foobar.h: #ifndef LIBRARY_FOOBAR_H #define LIBRARY_FOOBAR_H + // ... declarations ... + #endif // LIBRARY_FOOBAR_H ``` ##### Enforcement -`#include`보호 문구가 없는 `.h` 파일이 있다면 표시한다 +`#include`가드가 없는 `.h` 파일이 있다면 표시한다 ##### Note -Some implementations offer vendor extensions like `#pragma once` as alternative to include guards. -It is not standard and it is not portable. It injects the hosting machine's filesystem semantics -into your program, in addition to locking you down to a vendor. -Our recommendation is to write in ISO C++: See [rule P.2](#Rp-Cplusplus). +어떤 경우는 컴파일러에서 제공하는 확장(vendor extnsion)인 `#pragma once`를 대신 사용하기도 한다. +이는 표준이 아니며 모든 컴파일러가 제공하는 것은 아니다(not portable). +이 방법은 당신의 프로그램을 생성할 때 빌드를 수행하는 기계의 파일시스템 문맥을 사용하도록 만든다. 그 결과 해당 컴파일러/기계의 제공자(vendor)에 의존하게 된다. + +ISO C++ 를 따라서 작성할 것을 권한다: [P.2](./Philosophy.md#Rp-Cplusplus)를 읽어보라 -### SF.9: Avoid cyclic dependencies among source files +### SF.9: 소스 파일들이 순환 의존(cyclic dependencies)하게 하지마라 ##### Reason + 순환은 이해하기 어렵고, 컴파일 속도도 느려지게 한다. -향후 언어에서 모듈 기능을 지원할 때 이를 사용하도록 변경하기 어렵게 된다. +향후 언어에서 모듈 기능을 지원할 때 이 기능을 사용하도록 변경하기 어렵게 된다. ##### Note @@ -377,15 +386,15 @@ Our recommendation is to write in ISO C++: See [rule P.2](#Rp-Cplusplus). ##### Enforcement -Flag all cycles. +순환이 있으면 지적한다. -### SF.10: Avoid dependencies on implicitly `#include`d names +### SF.10: 묵시적으로 `#include`된 이름이 필요하지 않도록 하라 ##### Reason -Avoid surprises. -Avoid having to change `#include`s if an `#include`d header changes. -Avoid accidentally becoming dependent on implementation details and logically separate entities included in a header. +이상 행동(surprise)을 막는다. +`#include`되는 파일이 바뀌었을 때 `#include`하는 코드가 바뀔 필요가 없어야 한다. +구현 세부사항이나 해더파일에 있는 논리적으로 분리된 개체에 의존하게 되지 않도록 한다. ##### Example @@ -397,19 +406,18 @@ Avoid accidentally becoming dependent on implementation details and logically se { string s; cin >> s; // fine - getline(cin, s); // error: getline() not defined - if (s == "surprise") { // error == not defined + getline(cin, s); // error: getline()이 정의되지 않았다 + if (s == "surprise") { // 컴파일 오류. == 연산자가 정의되지 않았다 // ... } } ``` -`` exposes the definition of `std::string` ("why?" makes for a fun trivia question), -but it is not required to do so by transitively including the entire `` header, -resulting in the popular beginner question "why doesn't `getline(cin,s);` work?" -or even an occasional "`string`s cannot be compared with `==`). +``은 `std::string`의 정의를 사용할 수 있게 노출시킨다 ("어째서?"는 꽤 재미있는 질문이 될 것이다). +하지만 ``헤더를 사용해서 그 내용을 전파시키는(by transitively) 방식을 사용해야 한다고 어떤 요구사항이 존재하는 것은 아니다. +그 결과 많은 초심자들이 "왜 `getline(cin,s);`가 동작하지 않는거죠?"라거나, 때로는 "문자열을 `==` 연산자로 비교할수 없어요"라고 질문한다. -The solution is to explicitly `#include `: +해결방법은 명시적으로 `#include `를 추가하는 것이다: ```c++ #include @@ -429,8 +437,8 @@ The solution is to explicitly `#include `: ##### Note -Some headers exist exactly to collect a set of consistent declarations from a variety of headers. -For example: +어떤 헤더파일들은 그저 여러 헤더들을 똑같은 형태로(일관적으로) 가져오기 위해서만 존재하기도 한다. +예를 들어: ```c++ // basic_std_lib.h: @@ -443,26 +451,28 @@ For example: #include ``` -a user can now get that set of declarations with a single `#include` +이렇게 하면 사용자는 한번의 `#include`로 일련의 선언들을 가져올 수 있다. ```c++ #include "basic_std_lib.h" ``` -This rule against implicit inclusion is not meant to prevent such deliberate aggregation. +이 규칙은 "묵시적 include가 편의를 위해 사용되기 위한 기능이 아니다"라는 규칙에 반대된다. + +> implicit inclusion is not meant to prevent such deliberate aggregation ##### Enforcement Enforcement would require some knowledge about what in a header is meant to be "exported" to users and what is there to enable implementation. No really good solution is possible until we have modules. -### SF.11: Header files should be self-contained +### SF.11: 헤더 파일은 독립적으로 사용할 수 있게(self-contained) 만들어라 ##### Reason -Usability, headers should be simple to use and work when included on their own. -Headers should encapsulate the functionality they provide. -Avoid clients of a header having to manage that header's dependencies. +사용성, 헤더는 단순하게 사용할 수 있어야 하며 그 자신만 있어도 동작해야 한다. +헤더는 제공하는 기능을 캡슐화해야 한다. +헤더를 사용하는 쪽에서 헤더의 의존성을 관리하게 하지마라. ##### Example @@ -479,46 +489,52 @@ Failing to follow this results in difficult to diagnose errors for clients of a A test should verify that the header file itself compiles or that a cpp file which only includes the header file compiles. -### SF.20: Use `namespace`s to express logical structure +### SF.20: `namespace`는 논리적 구조를 표현할 때 사용하라 ##### Reason - ??? +??? ##### Example +``` ??? +``` ##### Enforcement ??? -### SF.21: Don't use an unnamed (anonymous) namespace in a header +### SF.21: 헤더에서 이름없는(anonymous) 네임스페이스를 사용하지 마라 ##### Reason -헤더 파일에 있는 익명 이름공간 거의 대부분이 버그이다. +헤더 파일에 있는 익명 네임스페이스 거의 대부분이 버그이다. ##### Example +``` ??? +``` ##### Enforcement -* 헤더 파일에서 사용되는 익명 이름공간을 찾아내 표시한다 +* 헤더 파일에서 사용되는 익명 네임스페이스을 찾아내 표시한다 -### SF.22: Use an unnamed (anonymous) namespace for all internal/nonexported entities +### SF.22: 이름없는(anonymous) 네임스페이스는 내부(internal)/노출시키지 않는(non-exported) 개체에 사용하라 ##### Reason -어떤 외부에서도 내부의 익명 이름공간에 있는 항목들에 참조할 수 없다. -소스 파일에 정의되어 있는 모든 구현들 중 "외부에 노출되는" 항목의 정의를 뺀 나머지 모두는 익명 이름공간에 넣는다 생각하라. +어떤 외부에서도 내부의 익명 네임스페이스에 있는 항목들에 참조할 수 없다. +소스 파일에 정의되어 있는 모든 구현들 중 "외부에 노출되는" 항목의 정의를 뺀 나머지 모두는 익명 네임스페이스에 넣는다 생각하라. ##### Example -API 클래스와 그 멤버들은 익명 이름공간에 있을 수 없지만, 구현 소스 파일에 정의된 "도우미" 클래스나 함수들의 경우 익명 이름공간 영역에 정의되어야 한다. +API 클래스와 그 멤버들은 익명 네임스페이스에 있을 수 없지만, 구현 소스 파일에 정의된 "도우미" 클래스나 함수들의 경우 익명 네임스페이스 영역에 정의되어야 한다. +``` ??? +``` ##### Enforcement From a94bd1a8802872246a968c771cdbe400b322ef6b Mon Sep 17 00:00:00 2001 From: luncliff Date: Wed, 3 Jul 2019 02:39:20 +0900 Subject: [PATCH 5/7] SF: except SF.4 --- sections/Expr.md | 3 +- sections/Source.md | 171 ++++++++++++++++++-------------- sections/appendix/DIscussion.md | 3 +- 3 files changed, 98 insertions(+), 79 deletions(-) diff --git a/sections/Expr.md b/sections/Expr.md index 1d1640c..db52287 100644 --- a/sections/Expr.md +++ b/sections/Expr.md @@ -166,7 +166,8 @@ Not easy. ??? Look for messy loops, nested loops, long functions, absence of fun 가독성이 좋아진다. 리소스 점유를 최소화할 수 있다. 값의 잘못된 사용을 피할 수 있다. -**Alternative formulation**: 불필요하게 큰 스코프에 변수를 선언하지 마라 +**Alternative Formulation**: +불필요하게 큰 스코프에 변수를 선언하지 마라 ##### Example diff --git a/sections/Source.md b/sections/Source.md index c743fd4..31ecb8f 100644 --- a/sections/Source.md +++ b/sections/Source.md @@ -6,52 +6,51 @@ 소스 파일 규칙 요약: -* [SF.1: Use a `.cpp` suffix for code files and `.h` for interface files if your project doesn't already follow another convention](#Rs-file-suffix) -* [SF.2: A `.h` file may not contain object definitions or non-inline function definitions](#Rs-inline) -* [SF.3: Use `.h` files for all declarations used in multiple source files](#Rs-declaration-header) -* [SF.4: Include `.h` files before other declarations in a file](#Rs-include-order) -* [SF.5: A `.cpp` file must include the `.h` file(s) that defines its interface](#Rs-consistency) -* [SF.6: Use `using namespace` directives for transition, for foundation libraries (such as `std`), or within a local scope (only)](#Rs-using) -* [SF.7: Don't write `using namespace` at global scope in a header file](#Rs-using-directive) -* [SF.8: Use `#include` guards for all `.h` files](#Rs-guards) -* [SF.9: Avoid cyclic dependencies among source files](#Rs-cycles) -* [SF.10: Avoid dependencies on implicitly `#include`d names](#Rs-implicit) -* [SF.11: Header files should be self-contained](#Rs-contained) - -* [SF.20: Use `namespace`s to express logical structure](#Rs-namespace) -* [SF.21: Don't use an unnamed (anonymous) namespace in a header](#Rs-unnamed) -* [SF.22: Use an unnamed (anonymous) namespace for all internal/nonexported entities](#Rs-unnamed2) - -### SF.1: Use a `.cpp` suffix for code files and `.h` for interface files if your project doesn't already follow another convention +* [SF.1: SF.1: 다른 관례를 따르는 중이 아니라면 `.cpp`는 코드 파일에, `.h`는 인터페이스 파일에 사용하라](#Rs-file-suffix) +* [SF.2: `.h` 파일에는 개체 변수(object definition) 혹은 inline이 아닌 함수의 정의가 있어서는 안된다](#Rs-inline) +* [SF.3: `.h` 파일은 여러 소스 파일에서 사용되는 선언을 담아라](#Rs-declaration-header) +* [SF.4: SF.4: 파일에서 무언가 선언하기 전에 `.h`를 include하라](#Rs-include-order) +* [SF.5: `.cpp`파일은 반드시 해당 인터페이스를 정의하는 `.h`를 include해야 한다](#Rs-consistency) +* [SF.6: `using namespace`는 네임스페이스의 이름 바꾸기, `std`처럼 기본적인 라이브러리, 혹은 지역 유효범위 안에서(만) 사용하라](#Rs-using) +* [SF.7: 헤더파일에서는 전체 유효범위(global scope)에 주는 `using namespace`를 작성하지 마라](#Rs-using-directive) +* [SF.8: 모든 `.h`파일에서 `#include` 가드(guard)를 사용하라](#Rs-guards) +* [SF.9: 소스 파일들이 순환 의존(cyclic dependencies)하게 하지마라](#Rs-cycles) +* [SF.10: 묵시적으로 `#include`된 이름이 필요하지 않도록 하라](#Rs-implicit) +* [SF.11: SF.11: 헤더 파일은 독립적으로 사용할 수 있게(self-contained) 만들어라](#Rs-contained) +* [SF.20: `namespace`는 논리적 구조를 표현할 때 사용하라](#Rs-namespace) +* [SF.21: 헤더에서 이름없는(anonymous) 네임스페이스를 사용하지 마라](#Rs-unnamed) +* [SF.22: 이름없는(anonymous) 네임스페이스는 내부(internal)/노출시키지 않는(non-exported) 개체에 사용하라](#Rs-unnamed2) + +### SF.1: 다른 관례를 따르는 중이 아니라면 `.cpp`는 코드 파일에, `.h`는 인터페이스 파일에 사용하라 ##### Reason -오래된 관례이다. 하지만 일관성이 더 중요하다. 프로젝트가 무엇인가 사용하고 있다면, 그대로 따라가라 + +오래된 관례다. 다만 일관성이 더 중요하다. +프로젝트에서 이미 어떤 파일 확장자 규칙을 사용하고 있다면, 그대로 따라가라 ##### Note -This convention reflects a common use pattern: -Headers are more often shared with C to compile as both C++ and C, which typically uses `.h`, -and it's easier to name all headers `.h` instead of having different extensions for just those headers that are intended to be shared with C. -On the other hand, implementation files are rarely shared with C and so should typically be distinguished from `.c` files, -so it's normally best to name all C++ implementation files something else (such as `.cpp`). +이 관례는 코드 사용패턴에 영향을 준다: +헤더는 C 언어와 함께 사용되는 경우가 자주 있기 때문에 일반적으로 `.h`를 사용한다. +그리고 그렇게 사용되는것을 의도했다면 다른 파일 확장자를 쓰는것보다 모두가 `.h`를 사용하는것이 쉽다. +반면에, 구현 파일이 C 언어와 함께 사용되는 경우는 드물기 때문에 `.c` 파일들과는 구분될 필요가 있다. 모든 C++ 파일들이 `.cpp`처럼 다른 확장자를 사용하는게 최선의 방법이다. `.h` 와 `.cpp`가 기본적으로 권장되기는 하지만 필수는 아니다. 다른 이름들도 광범위하게 사용된다. 예를 들자면 `.hh`, `.C`, `.cxx` 같은 것이 있다. 이런 이름을 같이 써도 좋다. -In this document, we refer to `.h` and `.cpp` as a shorthand for header and implementation files, -even though the actual extension may be different. +이 문서에서는, 실제로는 다른 확장자를 사용할수도 있겠지만, `.h`를 헤더파일에 대한 약칭(shorthand)으로, `.cpp`를 구현파일에 대한 약칭으로 사용한다. -Your IDE (if you use one) may have strong opinions about suffices. +당신이 사용하고있는 IDE에서는 특정한 확장자만 지원할수도 있다. ##### Example ```c++ // foo.h: - extern int a; // a declaration + extern int a; // 선언 extern void foo(); // foo.cpp: - int a; // a definition + int a; // 정의 void foo() { ++a; } ``` @@ -61,18 +60,19 @@ Your IDE (if you use one) may have strong opinions about suffices. ```c++ // foo.h: - int a; // a definition + int a; // 헤더 파일에 정의가 있다 void foo() { ++a; } ``` -`#include` 문구가 한 프로그램 내에 두 번 이상 포함된다면 단일 정의 규칙(one-definition-rule)에 위배된다고 링커가 오류를 낼 것이다. +`#include ` 문구가 한 프로그램 내에 2회 이상 포함된다면 +단일 정의 규칙(one-definition-rule)에 위배된다고 링커가 오류를 낼 것이다. ##### Enforcement -* Flag non-conventional file names. -* Check that `.h` and `.cpp` (and equivalents) follow the rules below. +* 관례에 맞지 않는 파일 이름들을 지적한다 +* `.h`와 `.cpp`가 (그리고 비슷한 파일들이) 아래 규칙을 따르는지 확인한다 -### SF.2: A `.h` file may not contain object definitions or non-inline function definitions +### SF.2: `.h` 파일에는 개체 변수(object definition) 혹은 inline이 아닌 함수의 정의가 있어서는 안된다 ##### Reason @@ -96,26 +96,28 @@ Your IDE (if you use one) may have strong opinions about suffices. // ... more ... ``` -Linking `file1.cpp` and `file2.cpp` will give two linker errors. +`file1.cpp`와 `file2.cpp`가 링킹될 때 링커 오류가 발생할 것이다. + +**Alternative Formulation**: -**Alternative formulation**: `.h` 파일은 다음의 항목만을 가진다: +`.h` 파일은 다음의 항목만을 가진다 -* `#include`s of other `.h` files (possibly with include guards) -* templates -* class definitions -* function declarations -* `extern` declarations -* `inline` function definitions -* `constexpr` definitions -* `const` definitions -* `using` alias definitions +* (include guard와 함께) 다른 `.h`의 `#include` +* 템플릿 +* 클래스 정의(definition) +* 함수 선언(declaration) +* `extern` 선언 +* `inline` 함수 정의 +* `constexpr` 정의 +* `const` 정의 +* `using` 별칭 * ??? ##### Enforcement 위의 목록에서 허용되는 것들을 검토한다 -### SF.3: Use `.h` files for all declarations used in multiple source files +### SF.3: `.h` 파일은 여러 소스 파일에서 사용되는 선언을 담아라 ##### Reason @@ -133,13 +135,14 @@ Linking `file1.cpp` and `file2.cpp` will give two linker errors. ``` `bar`를 관리하는 사람이 그 타입을 바꾸고자 하더라도 `bar`의 모든 선언을 찾을 수가 없다. -`bar`를 사용하는 입장에서는 이 인터페이스가 완벽한지 알 수가 없다. 기껏해야 (나중에) 링커로부터 오류메시지를 받는 것이 고작이다. +`bar`를 사용하는 입장에서는 이 인터페이스가 완벽한지 알 수가 없다. +기껏해야 (나중에) 링커로부터 오류메시지를 받는 것이 고작이다. ##### Enforcement -* Flag declarations of entities in other source files not placed in a `.h`. +* 개체의 선언이 `.h`가 아니라 다른 소스파일에 있으면 지적하라 -### SF.4: Include `.h` files before other declarations in a file +### SF.4: 파일에서 무언가 선언하기 전에 `.h`를 include하라 ##### Reason @@ -174,22 +177,23 @@ Linking `file1.cpp` and `file2.cpp` will give two linker errors. There is an argument for insulating code from declarations and macros in header files by `#including` headers *after* the code we want to protect (as in the example labeled "bad"). -However + +하지만 * that only works for one file (at one level): Use that technique in a header included with other headers and the vulnerability reappears. * a namespace (an "implementation namespace") can protect against many context dependencies. * full protection and flexibility require modules. -**See also**: +##### See also * [Working Draft, Extensions to C++ for Modules](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4592.pdf) * [Modules, Componentization, and Transition](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0141r0.pdf) ##### Enforcement -Easy. +쉽다 -### SF.5: A `.cpp` file must include the `.h` file(s) that defines its interface +### SF.5: `.cpp`파일은 반드시 해당 인터페이스를 정의하는 `.h`를 include해야 한다 ##### Reason @@ -204,8 +208,14 @@ Easy. int foobar(int); // foo.cpp: - void foo(int) { /* ... */ } - int bar(double) { /* ... */ } + void foo(int) { + /* ... */ + } + + int bar(double) { + /* ... */ + } + double foobar(int); ``` @@ -222,25 +232,30 @@ Easy. // foo.cpp: #include - void foo(int) { /* ... */ } - int bar(double) { /* ... */ } - double foobar(int); // error: wrong return type + void foo(int) { + /* ... */ + } + int bar(double) { + /* ... */ + } + double foobar(int); // error: 반환 타입이 다르다 ``` -The return-type error for `foobar` is now caught immediately when `foo.cpp` is compiled. -The argument-type error for `bar` cannot be caught until link time because of the possibility of overloading, but systematic use of `.h` files increases the likelihood that it is caught earlier by the programmer. +이제 `foobar`의 반환 타입 오류는 `foo.cpp`를 컴파일 할때 알 수 있다. +`bar`의 인자타입이 다른 것은 중복정의일 수 있으므로 오류는 링크 시간에 확인할 수 있다. +하지만 `.h`를 사용하는 것으로 프로그래머가 더 일찍 오류를 잡아낼 수 있게 한다. ##### Enforcement ??? -### SF.6: Use `using namespace` directives for transition, for foundation libraries (such as `std`), or within a local scope (only) +### SF.6: `using namespace`는 네임스페이스의 이름 바꾸기, `std`처럼 기본적인 라이브러리, 혹은 지역 유효범위 안에서(만) 사용하라 ##### Reason - `using namespace` can lead to name clashes, so it should be used sparingly. - However, it is not always possible to qualify every name from a namespace in user code (e.g., during transition) - and sometimes a namespace is so fundamental and prevalent in a code base, that consistent qualification would be verbose and distracting. +`using namespace`를 쓰면 이름 충돌이 일어날 수 있다. 가능한 필요한 경우에만(sparingly) 사용되어야 한다. +하지만, 사용자 코드에서 항상 모든 이름을 네임스페이스까지 분명히 하는 것(to qualify every name)이 가능한 것은 아니다. +그리고 때로는 어느 네임스페이스가 너무 기본적이고 많은 곳에서 사용되기도 한다. 그런 경우 매번 네임스페이스를 명시(qualification)하는 것은 코드를 장황하게 만들고 집중하기 어렵게 만든다. ##### Example @@ -256,12 +271,12 @@ The argument-type error for `bar` cannot be caught until link time because of th // ... ``` -Here (obviously), the standard library is used pervasively and apparently no other library is used, so requiring `std::` everywhere -could be distracting. +이 코드는 (명백하게) 표준 라이브러리를 여럿 사용하고 있으며 다른 라이브러리는 사용하지 않는다는 것이 드러난다. +따라서 모든 곳에서 `std::`를 작성하도록 하는 것은 코드에 집중할 수 없게 만들 것이다. ##### Example -The use of `using namespace std;` leaves the programmer open to a name clash with a name from the standard library +`using namespace std;`를 사용한다는 것은 표준 라이브러리에서 사용중인 이름과 충돌이 발생할 수 있도록 허용하는 것이다. ```c++ #include @@ -275,23 +290,23 @@ The use of `using namespace std;` leaves the programmer open to a name clash wit } ``` -However, this is not particularly likely to lead to a resolution that is not an error and -people who use `using namespace std` are supposed to know about `std` and about this risk. +다만 이 예시는 오류가 아니도록 처리될 가능성이 특히 낮은 경우다. +그리고 `using namespace std`를 사용하는 사람은 `std`에 무엇이 있고 어떤 위험이 있는지 이해하고 있을 것이다. ##### Note -A `.cpp` file is a form of local scope. -There is little difference in the opportunities for name clashes in an N-line `.cpp` containing a `using namespace X`, -an N-line function containing a `using namespace X`, -and M functions each containing a `using namespace X`with N lines of code in total. +하나의 `.cpp`파일은 지역 범위로 생각할 수 있다. +N-줄짜리 `.cpp`가 `using namespace X`를 사용했을 때 충돌 가능성과 +N-줄짜리 함수가 `using namespace X`를 사용했을 때, +N-줄짜리 함수 M개가 각각 `using namespace X`를 사용했을 때는 차이가 있다. ##### Note -[Don't write `using namespace` in a header file](#Rs-using-directive). +[`using namespace`는 헤더파일에 작성하지 마라](#Rs-using-directive). ##### Enforcement -Flag multiple `using namespace` directives for different namespaces in a single source file. +소스 파일에서 다른 네임스페이스에 대해 `using namespace`가 여러차례 나타나면 지적하라 ### SF.7: 헤더파일에서는 전체 유효범위(global scope)에 주는 `using namespace`를 작성하지 마라 @@ -314,7 +329,9 @@ Flag multiple `using namespace` directives for different namespaces in a single bool copy(/*... some parameters ...*/); // some function that happens to be named copy int main() { - copy(/*...*/); // now overloads local ::copy and std::copy, could be ambiguous + copy(/*...*/); // now overloads local + // ::copy and std::copy, + // could be ambiguous } ``` @@ -463,8 +480,8 @@ ISO C++ 를 따라서 작성할 것을 권한다: [P.2](./Philosophy.md#Rp-Cplus ##### Enforcement -Enforcement would require some knowledge about what in a header is meant to be "exported" to users and what is there to enable implementation. -No really good solution is possible until we have modules. +이 규칙을 적용하려면 어떤 헤더파일이 사용자에게 "노출"되는지 알아야 하고 어떤 파일이 구현에서만 사용되는지 알아야 한다. +Module 기능을 사용할 수 있을때 까지는 좋은 해결방법이 마땅히 없다. ### SF.11: 헤더 파일은 독립적으로 사용할 수 있게(self-contained) 만들어라 diff --git a/sections/appendix/DIscussion.md b/sections/appendix/DIscussion.md index 00d2597..fbfe0a2 100644 --- a/sections/appendix/DIscussion.md +++ b/sections/appendix/DIscussion.md @@ -410,7 +410,8 @@ Resource management rule summary: Prevent leaks. Leaks can lead to performance degradation, mysterious error, system crashes, and security violations. -**Alternative formulation**: Have every resource represented as an object of some class managing its lifetime. +**Alternative Formulation**: +Have every resource represented as an object of some class managing its lifetime. ##### Example From 7cc6c13157dcfa098a5c900fd9cb881ce72c471f Mon Sep 17 00:00:00 2001 From: luncliff Date: Wed, 3 Jul 2019 02:48:57 +0900 Subject: [PATCH 6/7] fix: item titles of SF --- sections/Source.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sections/Source.md b/sections/Source.md index 31ecb8f..f31f8e0 100644 --- a/sections/Source.md +++ b/sections/Source.md @@ -6,7 +6,7 @@ 소스 파일 규칙 요약: -* [SF.1: SF.1: 다른 관례를 따르는 중이 아니라면 `.cpp`는 코드 파일에, `.h`는 인터페이스 파일에 사용하라](#Rs-file-suffix) +* [SF.1: 다른 관례를 따르는 중이 아니라면 `.cpp`는 코드 파일에, `.h`는 인터페이스 파일에 사용하라](#Rs-file-suffix) * [SF.2: `.h` 파일에는 개체 변수(object definition) 혹은 inline이 아닌 함수의 정의가 있어서는 안된다](#Rs-inline) * [SF.3: `.h` 파일은 여러 소스 파일에서 사용되는 선언을 담아라](#Rs-declaration-header) * [SF.4: SF.4: 파일에서 무언가 선언하기 전에 `.h`를 include하라](#Rs-include-order) @@ -16,7 +16,7 @@ * [SF.8: 모든 `.h`파일에서 `#include` 가드(guard)를 사용하라](#Rs-guards) * [SF.9: 소스 파일들이 순환 의존(cyclic dependencies)하게 하지마라](#Rs-cycles) * [SF.10: 묵시적으로 `#include`된 이름이 필요하지 않도록 하라](#Rs-implicit) -* [SF.11: SF.11: 헤더 파일은 독립적으로 사용할 수 있게(self-contained) 만들어라](#Rs-contained) +* [SF.11: 헤더 파일은 독립적으로 사용할 수 있게(self-contained) 만들어라](#Rs-contained) * [SF.20: `namespace`는 논리적 구조를 표현할 때 사용하라](#Rs-namespace) * [SF.21: 헤더에서 이름없는(anonymous) 네임스페이스를 사용하지 마라](#Rs-unnamed) * [SF.22: 이름없는(anonymous) 네임스페이스는 내부(internal)/노출시키지 않는(non-exported) 개체에 사용하라](#Rs-unnamed2) From 9c7ccd921d208d36a1240d8702485615684ae25e Mon Sep 17 00:00:00 2001 From: luncliff Date: Wed, 3 Jul 2019 09:21:07 +0000 Subject: [PATCH 7/7] SF: item 4 partial translate --- sections/Source.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sections/Source.md b/sections/Source.md index f31f8e0..a2797e3 100644 --- a/sections/Source.md +++ b/sections/Source.md @@ -175,14 +175,13 @@ ##### Note -There is an argument for insulating code from declarations and macros in header files by `#including` headers *after* the code we want to protect -(as in the example labeled "bad"). +헤더파일에서 보호하고 싶은 코드 *다음에* `#include`목록이 오도록 해서 선언과 매크로로부터 코드를 분리한다는 생각에는 논쟁이 있다. 하지만 -* that only works for one file (at one level): Use that technique in a header included with other headers and the vulnerability reappears. +* 이 방법은 하나의 파일에(한 단계)만 통한다: Use that technique in a header included with other headers and the vulnerability reappears. * a namespace (an "implementation namespace") can protect against many context dependencies. -* full protection and flexibility require modules. +* 완전히 보호하면서 유연성을 가지려면 언어에서 모듈을 지원해야 한다 ##### See also