2017-02-16 138 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。沒有錯誤,沒有警告,什麼都沒有。在提交框中,我並不那麼幸運。

/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); 
      ^

這些錯誤是有意義的,因爲我不包括tuple頭,但我不明白爲什麼這個代碼編譯在所有我的筆記本電腦。這裏發生了什麼?

+1

AppleClang的標題可能間接包含或std :: tuple定義的其他來源。你必須看看標題才能確定。 –

+1

非可移植代碼的問題在於它是......好吧,你能猜到嗎? –

回答

5

不同的編譯器有不同的頭文件。 C++頭文件與你正在使用的編譯器密切相關。

您可能擁有的是Clang的<iostream>本身#include的元組頭文件,無論出於何種原因;因此引用std::tuple的代碼只能通過<iostream>頭文件快速編譯。

當然,這將依賴於您的編譯器的具體行爲。

不同的編譯器有不同的頭文件。 C++標準不禁止一個頭文件自動包含另一個頭文件;但爲了使用特定的類,模板或其他資源,確保此類,模板或其他資源可供您的代碼參考的唯一方法是明確包含其頭文件。

3

允許使用標準標頭,但不要求包含其他標準標頭。 clang的iostream標題很可能直接或間接包含tuple。沒有標準的機制來診斷你是否因此而忘了標準標題。

4

不同的實現可能會選擇在其他頭文件中包含一些頭文件。您應該始終包含您使用的標題。如果你這樣做了,那麼它將與兩個編譯器一起編譯。看來,鐺包括<tuple><iostream>而gcc沒有。他們被允許以任何方式做,並且你必須確保包含你需要的標題。

+1

這是相反的。 –

+0

@JonathanWakely謝謝,修正 – user463035818

1

由特定編譯器編譯的代碼並不強制表示您的代碼是正確的。正如documentationstd::tuple所述,它需要包含頭文件<tuple>,違反該規則會導致代碼不正確,儘管編譯器沒有義務檢測它並提供診斷。

相關問題