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
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との対応表を作ってみました。
Posix | After Windows Vista |
pthread_cond_init | InitializeConditionVariable |
pthread_cond_timedwait | SleepConditionVariableCS SleepConditionVariableSRW |
pthread_cond_signal | WakeConditionVariable |
pthread_cond_broadcast | WakeAllConditionVariable |
pthread_cond_destroy | なし |
pthread_once | InitOnceExecuteOnce |
pthread_rwlock_init | InitializeSRWLock |
pthread_rwlock_destroy | なし |
pthread_rwlock_rdlock pthread_rwlock_unlock pthread_rwlock_wrlock |
AcquireSRWLockExclusive ReleaseSRWLockExclusive AcquireSRWLockShared ReleaseSRWLockShared |
できればC++プログラマーなら新しい標準規格である「C++0x」からは
std::unique_lock
再帰ロック不可な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__は存在しません。