C ++ 11サポートを確認するにはどうすればよいですか?


104

コンパイラがC ++ 11の特定の機能をサポートしているかどうかをコンパイル時に検出する方法はありますか?たとえば、次のようなもの:

#ifndef VARIADIC_TEMPLATES_SUPPORTED

#error "Your compiler doesn't support variadic templates.  :("

#else

template <typename... DatatypeList>
class Tuple
{
    // ...
}

#endif

2
「assert_variadic_template_support.hpp」と呼ばれるヘッダーを含めることができますtemplate <typename... Test> struct compiler_must_support_variadic_templates;。構文エラーは問題をすぐに明らかにします。(余談ですが、適切なエラーメッセージの方がはるかに優れています。)
GManNickG '19

この問題を解決する正しい方法は、構成テストです。
Joseph Garvin、2011

回答:


125

__cplusplusC ++コンパイラがサポートされているC ++標準のバージョンに設定する必要があるという名前の定数があります。

#if __cplusplus <= 199711L
  #error This library needs at least a C++11 compliant compiler
#endif

Visual Studio 2010 SP1では199711Lに設定されていますが、ベンダーが(部分的な)コンパイラーレベルのサポートを持っているだけで、C ++ 11がすべて変更された標準のC ++ライブラリを持っている場合、ベンダーがそれを大きくするかどうかはわかりません。

したがって、別の回答で言及されているBoostの定義は、たとえば、C ++ 11スレッドや標準の他の特定の部分がサポートされているかどうかを判断する唯一の健全な方法のままです。


37
C ++ 11はの値を__cplusplusに設定します201103L。これは、2011年の規格に完全に準拠していることを示しています。部分的な準拠やコンパイラの拡張については説明しません。__cplusplusがに設定されている場合は201103L、コンパイラーが完全に準拠しているか、ユーザーに依存しています。そうでない場合、それがサポートする機能を実際に判別することはできません。
キーストンプソン

1
g ++ 4.7.x(およびおそらく新しい)は、-std=c++11オプションが指定されている場合(これも)でこれを設定します-std=gnu++11。完全な機能ではありませんが、これを行います(4.8を使用すると、かなり接近します)。注-コンパイラがサポートするものと標準ライブラリで利用できるものの間にはギャップがあります。現在、4.7.xと4.8.xの両方に正規表現のサポートがありませんが、これはライブラリーであり、コンパイラー機能ではありません。
Nathan Ernst

1
なぜこれが受け入れられない答えなのかしら。また、この提案を使用して回答をさらに改善することもできます。
Iharob Al Asimi 2015

1
@KeithThompsonは私にとっては、両方のコード::ブロックとVisual Studioは、の値に設定__cplusplusする199711LC ++ 11のために
ドナルドダック

3
@DonaldDuck:厳密に言えば、いいえ、彼らはしていません。に設定__cplusplusするコンパイラ199711Lは、準拠するC ++ 11コンパイラではありません。彼らはおそらくそれらを正しく動作させるためのオプションを持っています。
キーストンプソン、

39

C ++ 11標準(§iso.16.8)で述べられているように:

名前__cplusplusは、C ++変換単位のコンパイル時に値201103Lに定義されます。

そのマクロの値を使用して、コンパイラがC ++ 11に準拠しているかどうかを確認できます。

さて、コンパイラがC ++ 11機能のサブセットをすべてサポートしているかどうかを確認する標準的な方法を探しているのであれば、標準的な移植可能な方法はないと思います。詳細については、コンパイラのドキュメントまたはstdライブラリヘッダーファイルを確認してください。


2
たとえば、static_assertはVS2010およびすべてのc ++ 11コパイラーでサポートされています。したがって、VS2010で設定された値以上の__cplusplusの値(つまり、> = 199711L)をチェックすると、問題ありません。
Paolo M

33

私はこれが非常に古い質問であることを知っていますが、この質問はしばしば見られる可能性があり、答えは少し時代遅れです。

C ++ 14標準の新しいコンパイラには、C ++ 11機能を含む機能をチェックする標準的な方法があります。包括的なページはhttps://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendationsにあります

要約すると、各機能には、で確認できる標準マクロが定義されています#ifdef。たとえば、ユーザー定義のリテラルをチェックするには、次のように使用できます

#ifdef __cpp_user_defined_literals

1
知らなかった。このシンプルな機能は遅くなると思いますが、それでもなお非常に便利です。特に__has_include()マクロです。
プラピン

22

小切手のサポートについては、C ++ 14およびその他。GCC 5.2.1でのテスト。

#include <iostream>

int main(){
        #if __cplusplus==201402L
        std::cout << "C++14" << std::endl;
        #elif __cplusplus==201103L
        std::cout << "C++11" << std::endl;
        #else
        std::cout << "C++" << std::endl;
        #endif

        return 0;
}

17

あなたはこれを使うことができます:

#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
    cout << "C++11 is supported";
#else
    cout << "C++11 is not supported";
#endif

C ++ 11の場合、Visual Studioを除くほとんどのコンパイラーは__cplusplusマクロを201103Lに設定しますが、Visual Studioのどのバージョンでも、199711LC ++ 11より前の他のコンパイラーで使用される値を設定します。このコードは、_cplusplusマクロ201103LをVisual Studioを除くすべてのコンパイラーと比較し、コンパイラーがVisual Studioの場合、Visual Studioのバージョンが2015以降であるかどうかを確認します。スタジオ2015、_MSC_VERマクロには値があります。この回答を1900参照してください)。


1
この答えは間違っています。g++ -std=c++98GCC 4.8で、それは間違って印刷しますC++11 is supported
パート

1
@pts申し訳ありませんが、タイプミスです。今すぐ修正する必要があります。
ドナルドダック

7

Boost.Configを使用せず、C ++ 11をサポートするコンパイラをテストする必要がある場合は、定数の値をチェックする__cplusplusことで実行できます。ただし、コンパイラーはC ++ 11標準の一般的な機能のほとんどをサポートしている可能性がありますが、仕様全体をサポートしているわけではありません。C ++ 11仕様にまだ100%準拠していない特定のVisual Studioコンパイラーのサポートを有効にする場合は、Visual Studio 2013でのコンパイルを可能にする次のコードスニペットを使用します。

#if defined(_MSC_VER)
#   if _MSC_VER < 1800 
#       error This project needs atleast Visual Studio 2013
#   endif
#elif __cplusplus <= 199711L
#   error This project can only be compiled with a compiler that supports C++11
#endif

Visual Studioのコンパイラのバージョンの完全なリストは、「Visual Studio 2008でコードをコンパイルしているかどうかを検出する方法」にあります。


6

従来のLinux / Unixの世界では、autoconfは従来、ライブラリーとコンパイラー機能の存在と、必要に応じてファイルで使用するconfig.hに配置するバグのテストに使用されます。


2
はい、autoconfを使用して機能をテストできますが、失敗または成功した場合に適切なマクロを生成して、上記のコードでテストできるようにする必要があります。したがって、この回答だけでは情報は追加されません。
マーティンヨーク

3
@LokiAstari:autoconfの動作はそうではありません。Autoconfには、configureスクリプトにテストソースファイルをコンパイルさせ、コンパイルの成功に基づいて#defineを0または1に設定させるマクロが用意されています。diverscuba23の答えは、OPが実際の問題の次善の解決策に到達していることを指摘することによって情報を提供します。
Joseph Garvin、2011


1

チェックがC ++ 11ライブラリの可用性(言語機能ではない)である場合(<array>ヘッダーなど)、次のことができ#if __has_include(<array>)ます。

チェック#if __cplusplus >= 201103Lすると、C ++ 11を使用していることが通知される場合がありますが、Xcodeの標準ライブラリバージョン設定などの他の設定では、新しいライブラリがまだ利用できない場合があります(それらのほとんどは異なる名前で利用できます<tr1/array>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.