2017-02-16 1 views
3

숙제를하면서 랩탑 컴퓨터의 컴파일러가 우리가 제출에 사용할 것으로 기대되는 컴퓨터의 컴파일러보다 훨씬 더 관대하다는 것을 알게되었습니다. 내 랩톱의 C++ 컴파일러는 AppleClang 7.0.2.7000181이고 제출 상자의 컴파일러는 g++ 4.9.2입니다. 생각해 보면 컴파일 안, 코드는 다음과 같습니다왜이 C++ 코드는 일부 컴파일러에서 컴파일되지만 다른 컴파일러에서는 컴파일되지 않습니까?

#include <iostream> 

std::tuple<int, int> foo() { 
    return std::make_tuple(1, 1); 
} 

int main() { 
    auto pair = foo(); 
    int x = std::get<0>(pair); 
    int y = std::get<1>(pair); 
    std::cout << x << "," << y << std::endl; 
    return 0; 
} 

나는 또한 가지고 CMakeLists.txt :

내 노트북에
cmake_minimum_required(VERSION 2.8) 
project(foo) 

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Werror -Werror=sign-compare") 

set(SOURCE_FILES main.cpp) 
add_executable(foo ${SOURCE_FILES}) 

는 연타 행복이 코드를 컴파일하고 1,1을 출력합니다. 오류 없음, 경고 없음, 없음. 제출 상자에, 나는 그렇게 운이 좋다. 나는 tuple 헤더를 포함하고 있지 않다 때문에

/home/nate/foo/main.cpp: In function 'std::tuple<int, int> foo()': 
/home/nate/foo/main.cpp:3:26: error: return type 'class std::tuple<int, int>' is incomplete 
std::tuple<int, int> foo() { 
         ^
/home/nate/foo/main.cpp:4:12: error: 'make_tuple' is not a member of 'std' 
    return std::make_tuple(1, 1); 
      ^
/home/nate/foo/main.cpp: In function 'int main()': 
/home/nate/foo/main.cpp:8:21: error: 'void pair' has incomplete type 
    auto pair = foo(); 
        ^
/home/nate/foo/main.cpp:9:13: error: 'get' is not a member of 'std' 
    int x = std::get<0>(pair); 
      ^
/home/nate/foo/main.cpp:10:13: error: 'get' is not a member of 'std' 
    int y = std::get<1>(pair); 
      ^

이러한 오류

은 이해하지만,이 코드는 내 노트북에 전혀 컴파일 이유를 이해하지 않습니다. 무슨 일 이니?

+1

AppleClang의 헤더는 간접적으로 또는 std :: tuple 정의의 다른 소스를 포함 할 수 있습니다. 확실히 알기 위해서는 헤더를 봐야 할 것입니다. –

+1

이식성이 보장되지 않는 코드의 문제점은 ... 음, 잘 모르겠습니까? –

답변

5

다른 컴파일러는 다른 헤더 파일을 가지고 있습니다. C++ 헤더 파일은 사용중인 컴파일러와 밀접하게 연관되어 있습니다.

아마도 당신은 무엇이든간에 Clang의 <iostream> 자체 인 #include을 튜플 헤더 파일로 사용하고있을 것입니다. 따라서 std::tuple을 참조하는 코드는 <iostream> 헤더를 사용하여 #include으로 행복하게 컴파일됩니다.

물론 이것은 컴파일러의 특정 동작에 의존합니다.

다른 컴파일러에는 다른 헤더 파일이 있습니다. C++ 표준은 하나의 헤더 파일이 자동으로 다른 헤더 파일을 포함하는 것을 금지하지 않습니다. 특정 클래스, 템플릿 또는 기타 리소스를 사용하려면 코드에서이 클래스, 템플릿 또는 기타 리소스를 참조 할 수 있는지 확인하는 유일한 방법은 해당 헤더 파일을 명시 적으로 포함하는 것입니다.

3

표준 헤더는 허용되지만 다른 표준 헤더를 포함 할 필요는 없습니다. clang의 iostream 헤더에 직접 또는 간접적으로 tuple이 포함되어있을 가능성이 큽니다. 이 때문에 표준 헤더를 잊어 버린 것을 진단하는 표준 메커니즘이 없습니다.

4

다른 구현은 다른 헤더에 일부 헤더를 포함하도록 선택할 수 있습니다. 당신은 항상 당신이 사용하는 헤더를 포함해야합니다. 그렇게하면 두 컴파일러 모두로 컴파일됩니다. gcc는 <iostream>에 clang에 <tuple>이 포함 된 것 같습니다. 그들은 어느 쪽이든 그것을 할 수 있으며 필요한 헤더를 포함해야합니다.

+1

그것은 다른 방향입니다. –

+0

@JonathanWakely thanks, fixed – user463035818

1

코드가 특정 컴파일러에 의해 컴파일된다는 사실은 반드시 코드가 정확하다는 것을 의미하지는 않습니다. documentationstd::tuple으로 명시된 바와 같이, 헤더 <tuple>이 포함되어야합니다. 컴파일러가이를 감지하고 진단을 제공 할 의무는 없지만, 위반하면 코드가 잘못됩니다.

관련 문제