2017-02-16 8 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

異なる実装では、いくつかのヘッダーを他のヘッダーに含めることができます。あなたは常にあなたが使用するヘッダーを含める必要があります。もしあなたがそれをしたら、それは両方のコンパイラでコンパイルされます。 clccには<iostream><tuple>が含まれていますが、gccには含まれていないようです。彼らはそれをどちらかの方法で行うことが許されており、必要なヘッダーを確実に含める必要があります。

+1

これは逆です。 –

+0

@JonathanWakely thanks、fixed – user463035818

1

コードが特定のコンパイラでコンパイルされても、コードが正しいことが必須ではありません。 documentationstd::tupleに記載されているように、ヘッダ<tuple>が含まれている必要があります。違反すると、コードが不正になりますが、コンパイラはそれを検出して診断を行う必要はありません。

関連する問題