2011-07-26

gccとclangのC++0xサポートの比較

C++0xの規格はほぼ固まり、もはや変更されることはない。恐らく、このまま規格制定されるものと思われる。さて、今C++の主要なコンパイラーを上げるとすると、gccとclangをおいて他にはない。MSVCはオモチャだ。右の両コンパイラーは、C++0xの新機能を実装し始めている。もちろん、まだ不完全な実装も多いが、とりあえず遊べる程度には実装できている機能も多いので、比較してみることにする。

gccのC++0xサポート状況は、以下のページに簡易な一覧がある。

C++0x Support in GCC - GNU Project - Free Software Foundation (FSF)

clangのC++サポート状況は、以下のページに簡易な一覧がある。

Clang - C++ and C++'0x Status

面白いことに、どちらか片方のコンパイラーでしか実装されていない機能が、結構ある。ここで少し比較をしてみようと思う。もちろん、細かく観ていくときりがないので、大きな機能だけを紹介する。また、どちらのコンパイラーでも実装されている機能は省く。実装されていない機能は紹介する。

gccしか実装していない機能は、以下の通りである。

初期化リスト

std::vector<int> v = { 1, 2, 3, 4, 5 } ; // 便利便利

lambda

std::string str("表示するよ:") ; // キャプチャもできるよ
std::for_each( v.begin(), v.end(),
    [=](int i){ std::cout << str << i << std::endl ; }
) ;

ローカルクラスと無名クラスをテンプレート実引数に取る

template < typename T >
void f(T) { }

void g()
{
    struct X { } ;
    std::vector<X> v ; // ローカルクラスはOK

    enum { e1 } ;
    f( e1 ) ; // 無名クラスもOK
}

生文字列リテラル

char16_t const * ptr =
uR"(
ここには何でも書ける。
もちろん、\とかも書けるし、
この改行だって、ちゃんと改行として反映される。
ただし、\に続くuとUは使えないので注意。
"に続く(とか、)に続く"も書けない。
もちろん、連続しなければOK。
)" ;

unionの制限取っ払い

union U
{
    int x ;
    double d ;

    // 普通のクラスは余裕で持てる。
    std::string s ;

    // コンストラクターだって楽勝。
    U() : s("initialize") { }

    // メンバー関数もOK。virtual関数はダメだけど
    void f() { } 
} ;

constexpr

constexpr int twice( int x ) { return x * 2 ; }
template < int I > struct X { } ;
X< twice(100) > x ; // X<200>

clangしか実装していない機能は、以下の通りである。

コンストラクターのデリゲート(丸投げ)

struct X
{
    X( int i ) : X(i, 0) { } // 丸投げ
    X( int i1, int i2 ) { }
} ;

非staticデータメンバーの宣言の初期化子

struct X
{
    int m = 0 ;
    X() { } // mは0
    X( int i ) : m(i) { } // mはi
} ;

テンプレートエイリアス(エイリアス宣言も含む)

using A = int ;
A a ; // int
template < typename T >
using B = T ;
B<int> b ; // int
template < typename T >
using C = std::vector< T, CustomAllocator > ;
C<int> c ; // std::vector< int, CustomAllocator > 

まだどちらも実装していない機能

アトリビュート

[[]] int [[]] x ;

アライメント

struct X { int x ; double d ; } ;

void f()
{
    alignas(X) char a[100] ; // X型に要求されるアライメントを指定
    alignas(16) char b[100] ; // 16バイトアライメントを指定
    alignas(X, 4, float) char c[100] ; // X型と4バイトとfloat型とで、一番強いアライメント要求を指定

    alignof(int) ; // int型に要求されるアライメント(定数式)
}

コンストラクターの継承

struct Base
{
    Base() { }
    Base(int) { }
    Base(double) { }
} ;

struct Derived : Base
{
    // コンストラクターを継承
    using Base::Base ;
} ;

Derived d(0) ; // OK

ユーザー定義リテラル

void operator "" _owata ( char16_t *, std::size_t ) { }

int main()
{

uR"(
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄」
―――――――――――――‐┬┘
                        |
       ____.____    |
     |        |        |   |   
     |        | ∧_∧ |   |  
     |        |( ´∀`)つ ミ |   
     |        |/ ⊃  ノ |   |
        ̄ ̄ ̄ ̄' ̄ ̄ ̄ ̄    |    ミ ユーザー定義リテラル

)"_owata ;

}

No comments: