Windows版gcc4.4でC++0xのコードをコンパイルに`c++0x'だけではダメ


コンパイルオプションに`-std=c++0x'だけではダメで、`gnu++0x'も指定する必要があります。
(もしくは`gnu++0x'だけでも良いかもしれません。)

結論としては`-std=c++0x'ではなく、`-std=gnu++0x'を指定しなければいけません。


C++0xのコードをコンパイルするためのオプションとしては今のところ、
`-std=c++0x'と`-std=gnu++0x'があります。
`-std=c++0x'のみでコンパイルした場合、なんかをインクルードしていると

error: '::swprintf' has not been declared

なんて出てきます。
なので「-std=gnu++0x」オプションでコンパイルしてみると
コンパイルエラーがきれいになくなります。
ただ、この動作の理由は、/gcc/info/gcc.infoファイルの
`-std='オプション説明を読んでも書いてないなかったので
どうなってるのかは解りませんでした。
以下/gcc/info/gcc.infoの該当箇所を抜粋

`c++0x'
The working draft of the upcoming ISO C++0x standard. This
option enables experimental features that are likely to be
included in C++0x. The working draft is constantly changing,
and any feature that is enabled by this flag may be removed
from future versions of GCC if it is not part of the C++0x
standard.

`gnu++0x'
GNU dialect of `-std=c++0x'. This option enables experimental
features that may be removed in future versions of GCC.

`c++0x'はドラフト版のISO C++0x標準機能を有効にするオプションで、
`gnu++0x'は`-std=c++0x'の方言(別名でいいのかな?)オプション。
どちらも将来的には削除されるかもしれないオプションって書いてありますね。
/gcc/info/cpp.infoも見てみましたが

`__GXX_EXPERIMENTAL_CXX0X__'
This macro is defined when compiling a C++ source file with the
option `-std=c++0x' or `-std=gnu++0x'. It indicates that some
features likely to be included in C++0x are available. Note that
these features are experimental, and may change or be removed in
future versions of GCC.

`c++0x'または`gnu++0x'をつけると`__GXX_EXPERIMENTAL_CXX0X__'が
定義されるとしか書いてないです。
というわけで結論として今のところは面倒ですが
`c++0x'と`gnu++0x'のオプション両方を指定してコンパイルするのが
一番無難だと思います。



追記:nさんの指摘で一部内容を修正しました。

クラスのポインタをvoid*でdeleteした場合デストラクタが呼ばれない

意外と知らない人が多かったので簡単なサンプル

#include <iostream>

struct Hoge
{
    ~Hoge() { std::cout << __FUNCTION__ << std::endl; }
};

int main()
{
    Hoge* p = new Hoge;
    void* pv = p;
    delete pv;

    return 0;
}

実行結果 gcc4.4


実行結果 VC8


必ず正しいクラスのポインタでdeleteすること。

#include <iostream>

struct Hoge
{
    ~Hoge() { std::cout << __FUNCTION__ << std::endl; }
};

int main()
{
    Hoge* p = new Hoge;
    delete p;

    return 0;
}

実行結果 gcc4.4

~Hoge

実行結果 VC8

Hoge::~Hoge

Erase-Remove Ideomを少しでも楽に使うために。(自分用メモ)


こんな感じでコンテナの値を削除できるようにしてみた。

#include <algorithm>
#include <vector>

struct Hoge
{
    int num_;

    explicit Hoge(int i) : num_(i) {}
    int getnum() { return num_; }
};

int main(int argc, char** argv)
{
    std::vector<Hoge> v;
    v.push_back(Hoge(1));
    v.push_back(Hoge(1));
    v.push_back(Hoge(2));
    v.push_back(Hoge(2));
    v.push_back(Hoge(3));
    v.push_back(Hoge(3));

    // vからHoge::getnum() == 1なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_functor(&Hoge::getnum, 1)), // mem_equal_to_functorはHogeのメンバー関数getnumを呼び
            v.end());                                               // 1と比較してbool値を返す関数。
    // vからHoge::num_ == 3なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_member(&Hoge::num_, 3)),    // mem_equal_to_memberはHogeのメンバーnum_と
            v.end());                                               // 3を比較してbool値を返す関数。

    // vの中身を全て表示
    for(std::vector<Hoge>::iterator first = v.begin(), last = v.end(); first != last; ++first)
    {
        std:: cout << first->num_ << std::endl;
    }

    return 0;
}

実行結果

2
2

以下mem_equal_to_functor関数とmem_equal_to_member関数の実装付ソース。

// ----------------------------------------------------------------------------------------
#include <functional>

// メンバー関数用
template<class T, class U>
class mem_equal_to_functor_t
    : public std::binary_function<T, U, bool>
{
    U (T::*f_)();
public:
    explicit mem_equal_to_functor_t(U (T::*f)()) : f_(f) {}

    bool operator()(T& arg1, const U& arg2) const
    {
        return (arg1.*f_)() == arg2;
    }
};

// メンバー変数用
template<class T, class U>
class mem_equal_to_member_t
    : public std::binary_function<T, U, bool>
{
    U T::*member_;
public:
    explicit mem_equal_to_member_t(U T::*member) : member_(member) {}

    bool operator()(T& arg1, const U& arg2) const
    {
        return arg1.*member_ == arg2;
    }
};

// メンバー関数用関数オブジェクトを返す
template<class T, class U>
std::binder2nd<mem_equal_to_functor_t<T,U> >mem_equal_to_functor(U (T::*f)(), const U& u)
{
    return std::bind2nd(mem_equal_to_functor_t<T, U>(f), u);
}

// メンバー変数用関数オブジェクトを返す
template<class T, class U>
std::binder2nd<mem_equal_to_member_t<T,U> > mem_equal_to_member(U T::*m, const U& u)
{
    return std::bind2nd(mem_equal_to_member_t<T, U>(m), u);
}
// ----------------------------------------------------------------------------------------
#include <algorithm>
#include <vector>

struct Hoge
{
    int num_;

    explicit Hoge(int i) : num_(i) {}
    int getnum() { return num_; }
};

int main(int argc, char** argv)
{
    std::vector<Hoge> v;
    v.push_back(Hoge(1));
    v.push_back(Hoge(1));
    v.push_back(Hoge(2));
    v.push_back(Hoge(2));
    v.push_back(Hoge(3));
    v.push_back(Hoge(3));

    // vからHoge::getnum() == 1なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_functor(&Hoge::getnum, 1)), // mem_equal_to_functorはHogeのメンバー関数getnumを呼び
            v.end());                                               // 1と比較してbool値を返す関数。
    // vからHoge::num_ == 3なものを全て削除する
    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           mem_equal_to_member(&Hoge::num_, 3)),    // mem_equal_to_memberはHogeのメンバーnum_と
            v.end());                                               // 3を比較してbool値を返す関数。

    // vの中身を全て表示
    for(std::vector<Hoge>::iterator first = v.begin(), last = v.end(); first != last; ++first)
    {
        std:: cout << first->num_ << std::endl;
    }

    return 0;
}

実行結果

2
2

当然このままじゃまともには使えない。==にしか使えない時点でイケテナイ。
でもこれを発展させていけばboost::bind見たいなのが作れる。
もう少し発展させるとしたら引数にstd::less()等の関数オブジェクトを受け取れるようにして==以外も実行できるようにする。
ただ、ラムダ式さえ使えるようになれば以下のようにかけるのでこんなものは要らない。

    v.erase(std::remove_if(v.begin(),
                           v.end(),
                           [](Hoge& h) { return h.num_ == 1}),
            v.end());



ちなみに自分のプロジェクトではErase-Remove Ideom使ったら可読性が無いからダメって言われました。orz

boost::threadとstd::thread周りを調べてたら


こんな記事を見つけました。
http://msdn.microsoft.com/ja-jp/magazine/cc163405.aspx
以下記事内に書かれているWindows Vista以降で使用可能な関数とPosixとの対応表を作ってみました。

PosixAfter Windows Vista
pthread_cond_initInitializeConditionVariable
pthread_cond_timedwaitSleepConditionVariableCS
SleepConditionVariableSRW
pthread_cond_signalWakeConditionVariable
pthread_cond_broadcastWakeAllConditionVariable
pthread_cond_destroyなし
pthread_onceInitOnceExecuteOnce
pthread_rwlock_initInitializeSRWLock
pthread_rwlock_destroyなし
pthread_rwlock_rdlock
pthread_rwlock_unlock
pthread_rwlock_wrlock

AcquireSRWLockExclusive
ReleaseSRWLockExclusive
AcquireSRWLockShared
ReleaseSRWLockShared

できればC++プログラマーなら新しい標準規格である「C++0x」からは
ヘッダにある
std::unique_lockを要求するstd::condition_variable / ユーザ定義のlockとunlockを実装したクラスを受け取る std::condition_variable_any
ヘッダにある
再帰ロック不可なstd::mutex / 再帰ロック不可なタイマー付std::timed_mutex
再帰ロック可なstd::recursive_mutex / 再帰ロック可なタイマー付std::recursive_timed_mutex
スレッドセーフな1度だけの呼び出しにはstd::once_flagを使用したstd::call_once
を使ってほしいですせっかく標準でサポートされるわけですから。
使い方はこことかを読むと良くわかると思います。
C++0xのマルチスレッド機能


そういえばread write lockに相当するものはC++0xのmutexには含まれてないのですねー。
boostにも以前はread_write_mutexというのがあったのですがバグがあって今は無くなってます。
そんなわけで作ってみます。とか思ったけどすでに1年以上も前にmelponさんが作ってたのを見つけてしまいました。
melpon日記 - C++すら(ry Read-Write Lock
read_write_mutexのコードの部分をコピペして
#include

#include
#include
に修正して
boost::condition をstd::condition_variableに修正、
boost::mutex::scoped_lockはstd::uniqe_lockに直せば良いだけですかね。
#コードの中身は流し読みですw

__FUNCTION__マクロのwchar_t版


VCでは
char版は__FUNCTION__
wchar_t版は__FUNCTIONW__
ほかには__FILE__も__FILEW__が存在します。
xutilityヘッダに以下のように定義されてます。

 #define __STR2WSTR(str)    L##str
 #define _STR2WSTR(str)     __STR2WSTR(str)

 #define __FILEW__          _STR2WSTR(__FILE__)
 #define __FUNCTIONW__      _STR2WSTR(__FUNCTION__)

gccには__XXXW__は存在しません。

月曜日から


徹夜です。
3日おきにリリースとかアジャイルにもほどがあります。
今までガチガチのウォーターフォールでやってきたくせに!
ばか!


そいえば昨日The翻訳2009プレミアム専門辞書パック買いました。
おかげで今月と来月は金欠状態です。
本当にありがとうございます。


いっぱい翻訳がんばろう。