Top/article/Reference-type-of-element-of-std-vector-bool-is-NOT-bool
English | Japanese
English | Japanese

Menu

  • Top
  • Akihiko Yamaguchi 山口 明彦
  • Project プロジェクト
  • Text テキスト
  • Recent articles 最近の記事
  • Articles 記事一覧 (a to z)
  • Search 検索

Tags タグ †

  • [c++][bash][python][latex][php]
  • [linux][windows][mac][android]
  • [math][algorithm][idea][trick]
  • [liboctave][opencv][git][ros]
  • [setting][bug][general]
↑

Recent articles 最近の記事 †

2019-07-02
  • article/Display-Unix-Time
  • article/Synchronize-Linux-Time-to-Remote
2018-09-27
  • article/python-multimode-singleton
2018-09-02
  • article/rosinstall-git-default-remote
2017-07-28
  • article/SubMenu
2017-03-05
  • article/Import-a-different-version-of-OpenCV-in-Python
2015-08-17
  • article/DRC-finals-2015
2015-01-05
  • article/Upgrade-Android-to-Lollipop
2015-01-01
  • article/Kernel-panic-of-Linux-when-using-Xtion
  • article/Do-not-skip-freeing-data-when-using-tri-mesh-in-ODE
Access: 1/1861 - Admin
These search terms have been highlighted:[c++]

Reference type of an element of std::vector<bool> is NOT bool& (sometimes)

std::vector<bool>の要素の参照型はbool&ではない(場合がある)

[c++]
2012-03-07

std::vector<T>::back() を使うと,末尾の要素の参照を取得できる.これは普通は,T&型だ.ところが,T=bool に限っては,「std::_Bit_reference」型なのだ(少なくとも g++ の場合).

通常,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<bool> の参照型が std::_Bit_reference であることに起因する.std::_Bit_reference 型は bool& に変換することができないから,Func(bool&) の引数として使うとエラーとなるのだ.

(ちゃんと調べていないが,おそらく bit** という名前から,bool の vector はビット演算を使った効率化をしているものと予想される.)

このような実装は,STL の仕様を満たしていないのではないか? と思ってしまうが,std::vector<T> では,要素の値型 std::vector<bool>::value_type と要素の参照型 std::vector<bool>::reference の両方が独立に定義できるようになっているようで,必ずしも std::vector<bool>::value_type& と std::vector<bool>::reference が同じである必要はないようだ.(注:STLの仕様をちゃんと精査して書いていない)

↑

実験 †

上記コードの void Func(bool &x) を

void Func(vector<bool>::reference x)

と変更すれば,コンパイルは通るし,期待通りに動く.

↑

対策 †

ぱっと思いつく対策:

  • bool を参照渡しする必要は,通常ないと思われるので,値渡しする.
  • テンプレートで関数を共通化したい場合,std::vector<bool> については特殊化する.
  • もしくは,std::vector<T> の参照を取得するために T& や const T& を使うのではなく,std::vector<T>::reference や std::vector<T>::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<TBool> などと使う.




Last-modified:2015-01-01 (Thu) 09:31:01 (3836d)
Site admin: Akihiko Yamaguchi.
Written by: Akihiko Yamaguchi.
System: PukiWiki 1.5.0. PHP 5.2.17. HTML conversion time: 0.012 sec.