2011-03-04 4 views
7

나는 알고 #pragma once 표준 및 따라서 등 모든 컴파일러에서 지원하지 아니라고가드를 포함하고 싶지 않은 상황이 있습니까? 가드가 존재 등이 이유

내 질문은 다른 종류이다 :

사상을 가지고 있지 어떤 합리적인 이유가 ? 이론적으로, 어딘가에 포함시키려는 파일에 경비원을 포함시키지 않는 것이 유익 할 수있는 상황을 아직 보지 못했습니다. 누구든지 실제 혜택이없는 사례가 있습니까?

내가 물어 보는 이유는 - 항상 제멋대로 인 것처럼 보이고, #pragma once의 동작은 문자 그대로 모든 것에 자동으로 적용될 수 있습니다.

답변

8

내가 포함하기 전에 정의 된 매크로에 따라 코드를 생성하는 헤더를 보았습니다. 이 경우 매크로를 하나의 값으로 정의하고, 헤더를 포함하고, 매크로를 다시 정의하고, 다시 포함하려고합니다.
그런 사람들은보기 흉하고 피할 수 없다는 데 동의하지만 때때로 (헤더의 코드가 다른 수단에 의해 생성 된 것처럼) 그렇게하는 것이 더 나쁜 것입니다.

그 외, 나는 이유를 생각할 수 없다.

+0

나는 (아마도 지금은 바뀌이 전에 잠시에서 임) FFTW 라이브러리에서이 특정한 사용 건너했습니다. in, double, float 등 다양한 기본 유형에 대해 만들 수 있도록 여러 함수가 정의되어 있으므로 필요한만큼의 유형을 정의하고 파일을 다시 포함 할 수 있습니다. 그러나 이것은 C 라이브러리입니다. C++에서는 물론 템플릿을 사용합니다 ... –

+0

@the_mandrill : C++에서는 템플릿이 문제에 맞지 않는 일부 상황에서 실제로 사용됩니다. 특히 부스트 전 처리기 라이브러리를 사용하면 0, 1, 2 ... N 개의 인수로 'boost :: bind'에서와 같이 자동으로 다른 수의 인수로 동일한 코드를 생성 할 수 있습니다. –

+0

@David Rodríguez : 내가 아는 한 boost :: bind는 최대 9 개의 인수에 대해 적절한 템플릿을 제공함으로써 구현됩니다. 편집 : 좋아 내가 반환 부스트 (반환 유형이 무효입니다)로 템플릿 인수와 함수로'반환 x '상황을 피하기 위해 부스트를 찾았지만, 항상 특정 템플릿 전문화로 이것을 해결할 수 있었다. 타입'void'에 대해서. 그들은 include guard없이 route를 진행하지만,이 문제를 해결하기 위해'return' 매크로를 다시 정의 할 필요는 없습니다. – Mephane

0

동일한 포함 가드를 사용하는 프로젝트에 두 개의 헤더가있는 경우 문제가 될 수 있습니다. 두 개의 타사 라이브러리가 있고 둘 다 __CONSTANTS_H__과 같은 포함 가드 기호를 사용하는 헤더가있는 경우 지정된 컴파일 단위에서 두 헤더를 모두 #include 성공적으로 수행 할 수 없습니다. 더 나은 해결책은 #pragma once이지만 일부 오래된 컴파일러는이를 지원하지 않습니다.

+2

무엇보다'#pragma once' ___는 standard___가 아니기 때문에 컴파일러의 다음 버전이 여전히 그것을 지원하거나 동일한 의미를 지원한다는 보장은 없습니다. 나를 위해, 그것은 그것을 사용하지 않는 아주 좋은 이유입니다. – sbi

+1

@sbi : true - 이식성과 위에서 설명한 것과 같은 이슈 사이에서 절충되는 경우가 종종 있습니다. 나는 당신이 컴파일러와 컴파일러 버전을 테스트하고 그에 따라 가드 또는'#pragma once '를 적절하게 사용함으로써 당신이 항상 추악한 보일러 판을 he 수 있다는 것을 알았지 만, 모든 헤더에서 그걸보고 싶지는 않다. –

+0

두 명이 경비원을 포함한다면, 답은 생략하지 말고 그 중 하나를 변경하는 것입니다. – Mephane

0

타사 라이브러리가 있고 코드를 수정할 수 없다고 가정 해보십시오. 이제이 라이브러리의 파일을 포함하여 컴파일러 경고를 생성한다고 가정합니다. 일반적으로 높은 경고 수준에서 자신의 코드를 컴파일하려고하지만 이렇게하면 라이브러리 사용으로 인한 많은 경고가 생성됩니다. 제 3 자 라이브러리를 감쌀 수있는 경고 disabler/enabler 헤더를 작성할 수 있으며 여러 번 포함 할 수 있어야합니다. http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/index.html

+0

위의 래퍼에 경비원을 포함시키지 않으면 어떤 효과가 있는지 보지 못합니다. 래퍼를 이미 포함했다면, 이미 * include *에있는 제 3 자 헤더에 대한 경고가 비활성화되고, 래퍼를 두 번째로 포함하면 포함 가드에 의해 포착되고 전혀 포착되지 않습니다. – Mephane

+0

@Mephane : 경고가 튀어 나오는 라이브러리 헤더가 아니라 포함 가드없이 컴파일러 관련 경고 제어 pragma가 포함 된 헤더입니다. –

3
<cassert> 
<assert.h> 

는 "어설 션 매크로 NDEBUG의 현재 상태 < assert.h를이> 포함하는 각 시간에 따라 재정의 :

사용의 또 다른 더 정교한 종류의 부스트의 처리기 반복 구조입니다. "

4

@sbi는 이미 코드 생성에 대해 이야기 했으므로 예제를 들어 보겠습니다.

은 항목의 많은의 열거를 가지고, 당신은

하나의 솔루션이 다수 포함 트릭을 사용하는 것입니다 ...의 각 요소에 대한 기능의 무리를 생성하고 싶다고 말한다. 기능 모든 유틸리티를 통해 각각의 시간을 크롤링해야하지 귀하에게 달려 있습니다이 좋은 또는 hackish 여부

#define MY_ENUMERATION_META_FUNCTION(Item_) \ 
    case Item_: return #Item_; 

char const* print(MyEnum i) 
{ 
    switch(i) { 
    #include "myenumeration.td" 
    } 

    __unreachable__("print"); 
    return 0; // to shut up gcc 
} 

#undef MY_ENUMERATION_META_FUNCTION 

하지만 분명 유용합니다 :

// myenumeration.td 
MY_ENUMERATION_META_FUNCTION(Item1) 
MY_ENUMERATION_META_FUNCTION(Item2) 
MY_ENUMERATION_META_FUNCTION(Item3) 
MY_ENUMERATION_META_FUNCTION(Item4) 
MY_ENUMERATION_META_FUNCTION(Item5) 

그런 사람들은과 같이 사용 새로운 값이 열거 형에 추가됩니다.

+0

그리고 맨 위의 myenumeration.td에'#define MY_ENUMERATION_META_FUNCTION'을 넣으면 두 번째 파일을 * once *로 포함 할 수 있으며 첫 번째 파일을 한 번 포함 할 수 있습니다. 당신의 예제는 쉽게 피할 수있는 임의의 순환 포함 종속성처럼 보입니다. 내가 틀렸다면 나를 바로 잡아주세요. – Mephane

+0

@Mephane : "enumeration.td"에 아무것도 포함되어 있지 않다는 점을 감안할 때 순환 종속성이 어떻게 될지 이해하지 못합니다. 또한 매크로 'MY_ENUMERATION_META_FUNCTION'은 열거 파일에 정의되어 있지 않습니다. 그것의 메타 기능으로 사용, 그래서 거기에 그것을 정의하는 목적을 좀 물리 ​​칠 것입니다. –

+0

아, 이제 알겠습니다. 두 번째 파일은 재사용 할 코드가있는 다른 헤더가 아니라 실제 구현이며, 각 구현은 자체 버전의 MY_ENUMERATION_META_FUNCTION을 정의 할 수 있습니다. 그리고 네, 완전히 해킹 된 느낌입니다. 이 같은 일을 할 수 있는지 여부가 실제 이익인지 아닌지는 물론 주관적 일 수도 있지만 지금은 가능성을 알 수 있습니다. – Mephane

0

한 번 #pragma 문제는 표준에 포함되지 않은 이유는 모든 곳에서 작동하지 않는다는 것입니다. 컴파일러는 서로 다른 경로에서 포함 된 경우 두 파일이 같은 파일인지 여부를 어떻게 알 수 있습니까?

생각해 보면 컴파일러가 실수로 포함시켜야하는 파일을 포함하지 않으면 어떻게됩니까? 파일에 두 번 포함되어 있으면 안되나요? 어떻게 그걸 고칠 수 있니?

가드가 포함 된 경우 최악의 경우 컴파일하는 데 약간 시간이 걸릴 수 있습니다.

편집 : 이 스레드는 comp.std.C++에서 확인하십시오. "ISO 표준의 #pragma once yet?"

http://groups.google.com/group/comp.std.c++/browse_thread/thread/c527240043c8df92

+0

필자는'#pragma once'와'# define' include-guards의 차이점을 특별히 묻지 않고, 파일을 여러 번 포함시키고 자하는 올바른 상황을 위해 특별히 질문했습니다. – Mephane

+0

자, 왜 기본적으로 모든 곳에서 #pragma once가 없는지 묻습니다. 마지막 문장 에서처럼 ... –

+0

나는 원하는 효과 자체에 대해 더 많이 묻고 있었다. '#pragma once '는 include-guard와 같은 효과를 달성하는 수단이다. – Mephane