3

-Wc++11-extensions新しいバージョンのClangは、C++03モードでコンパイルするときに特定のC++11拡張機能をサポートしますが、オンにすると警告が表示される場合があります。たとえば、次のコードをコンパイルします。

std::map<int, int> foo;
for(auto &i : foo) {
}

clang test.cpp -std=c++03これらの警告の結果:

test.cpp:5:6: warning: 'auto' type specifier is a C++11 extension
      [-Wc++11-extensions]
        for(auto &i : foo) {
            ^
test.cpp:5:14: warning: range-based for loop is a C++11 extension
      [-Wc++11-extensions]
        for(auto &i : foo) {

ただし、コンパイルは成功し、正しいコードが生成されます。ただし、たとえば均一初期化(std::map<int, int> foo{{1,2},{3,4}};)を使用しようとすると、構文エラーで失敗します。

私の場合、互換性の問題があるため、C++03モードでのみコンパイルされる既存の不変のライブラリがあります。開発者は、「近い将来」にC++11をサポートすると述べています。今すぐC++11機能を使用してこのライブラリに対してコードを記述したいので、ライブラリをC ++ 11互換にしたときに、戻ってコードを「最新化」する必要はありません。ClangのC++11拡張機能はこの目的には理想的ですが、何を使用できるかわかりません。ClangのC++11拡張機能はどこかに文書化されていますか?

4

1 に答える 1

7

ここで使用できる「機能テスト」マクロは2つあります。

__has_feature__has_extension

これらの関数のようなマクロは、機能の名前である単一の識別子引数を取ります。__has_feature機能がClangでサポートされ、現在の言語標準で標準化されている__has_extension場合は1と評価され、機能が現在の言語でClangによってサポートされている場合(言語拡張または標準言語機能として)は1と評価されます。そうでない場合は0。

これらのマクロと識別子は、次の場所に記載されています。

http://clang.llvm.org/docs/LanguageExtensions.html

特定の例では、次のHelloWorldが最も有益です。

#if __has_extension(cxx_generalized_initializers)
#warning __has_extension(cxx_generalized_initializers) is true
#else
#warning __has_extension(cxx_generalized_initializers) is false
#endif

#if __has_feature(cxx_generalized_initializers)
#warning __has_feature(cxx_generalized_initializers) is true
#else
#warning __has_feature(cxx_generalized_initializers) is false
#endif

#if __has_extension(cxx_range_for)
#warning __has_extension(cxx_range_for) is true
#else
#warning __has_extension(cxx_range_for) is false
#endif

#if __has_feature(cxx_range_for)
#warning __has_feature(cxx_range_for) is true
#else
#warning __has_feature(cxx_range_for) is false
#endif

int main()
{
}

私の場合、-std = c ++ 03を使用すると、次のように出力されます。

test.cpp:4:2: warning: __has_extension(cxx_generalized_initializers) is false [-W#warnings]
#warning __has_extension(cxx_generalized_initializers) is false
 ^
test.cpp:10:2: warning: __has_feature(cxx_generalized_initializers) is false [-W#warnings]
#warning __has_feature(cxx_generalized_initializers) is false
 ^
test.cpp:14:2: warning: __has_extension(cxx_range_for) is true [-W#warnings]
#warning __has_extension(cxx_range_for) is true
 ^
test.cpp:22:2: warning: __has_feature(cxx_range_for) is false [-W#warnings]
#warning __has_feature(cxx_range_for) is false
 ^
4 warnings generated.

一方、-std = c ++ 11を使用すると、出力は次のように変わります。

test.cpp:2:2: warning: __has_extension(cxx_generalized_initializers) is true [-W#warnings]
#warning __has_extension(cxx_generalized_initializers) is true
 ^
test.cpp:8:2: warning: __has_feature(cxx_generalized_initializers) is true [-W#warnings]
#warning __has_feature(cxx_generalized_initializers) is true
 ^
test.cpp:14:2: warning: __has_extension(cxx_range_for) is true [-W#warnings]
#warning __has_extension(cxx_range_for) is true
 ^
test.cpp:20:2: warning: __has_feature(cxx_range_for) is true [-W#warnings]
#warning __has_feature(cxx_range_for) is true
 ^
4 warnings generated.

ユースケースでは、コードをひもで締めて__has_extension(cxx_generalized_initializers)、trueの場合は新機能を使用し、falseの場合は回避することができます。その後、clangをアップグレードしたり、使用する言語モードが変更されたりすると、コードが自動的に適応します。

サポートされている言語機能とサポートされていない言語機能については、ドキュメントが役立つ場合がありますが、上記のようなテストを作成することが、現在のclangバージョンを評価するための最も高速で正確な方法であることがわかります。

于 2013-03-24T18:53:33.490 に答える