2017-02-16 122 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>,违反该规则会导致代码不正确,尽管编译器没有义务检测它并提供诊断。

相关问题