std::vectorの要素の参照型はbool&ではない(場合がある)
std::vector
通常,bool を関数の引数として渡すとき,わざわざ参照渡ししようとは思わないから(別に効率がよくなるわけではない),意識する必要はないのだが,テンプレート関数やクラスを作る場合には,知っておかないと理解不能なエラーに直面することがある.なので,忘備録も兼ねてメモ.
例
#include <vector> using namespace std; void Func(bool &x) { x= false; } int main(int argc, char**argv) { vector<bool> vec; vec.push_back(true); Func(vec.back()); return 0; }
これを,コンパイルすると,g++ の場合は,Func(vec.back()); に対して
error: invalid initialization of non-const reference of type ‘bool&’ from a temporary of type ‘std::_Bit_reference’
というエラーを吐く.
これは,bool 限定だ.bool を double や int に変更すれば,何の問題もなくコンパイルできる.
分析
このエラーは,冒頭で述べたとおり,std::vector
(ちゃんと調べていないが,おそらく bit** という名前から,bool の vector はビット演算を使った効率化をしているものと予想される.)
このような実装は,STL の仕様を満たしていないのではないか? と思ってしまうが,std::vector
対策
ぱっと思いつく対策:
- bool を参照渡しする必要は,通常ないと思われるので,値渡しする.
- テンプレートで関数を共通化したい場合,std::vector
については特殊化する. - もしくは,std::vector
の参照を取得するために T& や const T& を使うのではなく,std::vector ::reference や std::vector ::const_reference を使う.
(追記)
- 次のような bool のラッパを用いるのもひとつの手だ.
class TBool { public: TBool() : entity_(false) {} TBool(bool e) : entity_(e) {} TBool(const TBool &b) : entity_(b.entity_) {} operator bool&() {return entity_;} operator const bool&() const {return entity_;} private: bool entity_; };
std::vector