2015-02-06 5 views
3

최적화 설정 (-O3 대 none)에 따라 출력이 다른 예제를 찾았지만 -std=c++11 -Wall -pedantic 옵션이 있더라도 GCC 4.8.2는 경고를 표시하지 않습니다.최적화 옵션에 따라 다른 동작

이 특별한 경우에 나는 header.h의 주석 처리 된 줄을 "잊어 버린"것이 실수이며, -O3과 함께 c<int>::get()이 인라인 된 것으로 가정합니다.

그러나 이러한 종류의 실수 (컴파일러 또는 링커 옵션)로부터 자신을 보호 할 수있는 방법이 있습니까?

header.h가 :

#ifndef HEADER_H 
#define HEADER_H 

template<class T> 
struct c 
{ 
    int get() { return 0; } 
}; 

// template<> int c<int>::get(); 

#endif 

imp.cpp :

#include "header.h" 

template<> 
int c<int>::get() 
{ 
    return 1; 
} 

MAIN.CPP :

#include <iostream> 
#include "header.h" 

int main() 
{ 
    c<int> i; 
    std::cout << i.get() << '\n'; // prints 0 with -O3, and 1 without 
} 

빌드 :

c++ -std=c++11 -pedantic -Wall -O3 -c imp.cpp 
c++ -std=c++11 -pedantic -Wall -O3 -c main.cpp 
c++ -std=c++11 -pedantic -Wall -O3 imp.o main.o 
+2

동작이 어떻게 다른가요? – molbdnilo

답변

6
  1. 헤더 파일에 해당 줄이 있으면 얻을 수있는 것은 해당 멤버 함수에 대한 명시 적 특수화의 선언입니다.

    따라서 main.cpp는 다른 컴파일 단위의 정의를 보장하며 모든 것이 작동합니다.

  2. 당신이 그것을 떠날 경우, ODR의 위반이 : 클래스 템플릿의 특정 인스턴스가 컴파일 - 단위로 다른

    것을. 결과적으로 "부적절하고 진단이 필요하지 않습니다."

    그리고 현재 gcc가 진단하도록 컴파일러 옵션이 없습니다.

0

여기에서 진정한 실수는 소스 파일을 레이아웃하고 빌드하는 것입니다. c<int>::get()을 사용하는 경우 템플리트를 인스턴스화하기 위해 해당 정의를 사용할 수 있어야합니다. 이 문제를 해결하려면 header.h은 다른 방법이 아닌 #include "imp.cpp"이어야합니다. imp.cppimp.inl 또는 다른 이름으로 바꿀 수도 있습니다.

단일 .cpp 파일 외부에서 사용되는 템플릿을 정의 할 때 해당 정의가 머리글을 포함하는 모든 사람에게 표시되어야합니다.

제쳐두고 : 저는 컴파일러를 만들거나 링커가 여기에서 한 것에 대해 경고하는 방법이 없다고 생각합니다. 그러나 앞서 설명한 것처럼 프로젝트를 구조화하면 앞으로 선언 할 필요가 없으므로이 문제는 발생하지 않습니다.

+1

* 단일 .cpp 파일 외부에서 사용되는 템플릿을 정의 할 때 해당 정의가 헤더를 포함하는 모든 사람에게 표시되어야합니다. * http://stackoverflow.com/a/의 마지막 (네 번째) 코드 조각이 아니겠습니까? 495056/1937197이 일반 규칙에 위배됩니까? – MaxB

+0

@MaxB : 명시 적 템플릿 인스턴스화는 대부분의 사람들이 신경 쓰지 않는 고급 사용 사례입니다. 당신은 그것이 일반적인 규칙의 예외라는 것이 옳습니다 ...하나는 명시 적 인스턴스 모델로 이동하면 머리말에서 모든 것을 이동한다는 것을 알 수 있으므로 (OP와 마찬가지로 모든 것의 절반이 아님) 안전하게 무시할 수있는 매개 변수입니다. –

관련 문제