2013-03-07 10 views
7

これは安全な回避策ですか?私はベクトルboolを使用したいが、Cスタイルの配列を期待する古いコードへのポインタを渡す必要がある。ベクトル<bool>を回避するには、basic_string <bool>を使用しますか?

typedef std::basic_string<bool> vector_bool; 

int main() 
{ 
    vector_bool ab; 
    ab.push_back(true); 
    ab.push_back(true); 
    ab.push_back(true); 
    ab.push_back(false); 
    bool *b = &ab[0]; 
    b[1] = false; 
} 

編集:他のソリューションの提案のため おかげで、私は本当に私の上記の溶液に明確な答えをしたいと思います。ありがとう。

+2

古いコードでは、パックされたビットまたは各ブールが個別にアドレス可能な場所にありますか? – us2012

+0

それぞれのブールは、古典的なbool myarray [n]と同じように別々です。 –

+2

ベクトルはどうですか? – jrok

答えて

15

ことがstd::char_traits<bool>をインスタンス化しますので、私はstd::basic_string<bool>についてはよく分からないし、標準を定義することを必要とする場合、またはchar_traits主テンプレートは、char_traits<char>されているものとしてのみ明示的に特化して、未定義のままにすることができた場合、私はわからないんだけど定義された。スペシャライゼーションがユーザー定義タイプに依存している場合、標準テンプレートのみを専門にすることができるので、boolは明らかではありません。char_traits<bool>の独自のスペシャリゼーションを提供することはできません。あなたのstdlibがデフォルトのchar_traitsの定義を持っていて、char_traitsのメンバーに何か役に立つものを必要とする文字列操作を使用しようとしないなら、それはうまくいくかもしれません。

また、これはハックですが、うまくいくかもしれない:

struct boolish { bool value; }; 
inline boolish make_boolish(bool b) { boolish bish = { b }; return bish; } 

std::vector<boolish> b; 
b.push_back(make_boolish(true)); 
bool* ptr = &b.front().value; 

boolishは些細なタイプですので、限りboolishの配列は、あなたに必要があると思いboolの配列(同じ表現を持つようあなたのコンパイラをチェックしてください。を使ってパディングがないことを確認しました。)*ptr*++ptrは同じ配列の一部ではないので、おそらくエイリアスの規則に違反しますが、ポインタをインクリメントすることはできません。 boolish::valueを指していれば、それは前のものの "最後を過ぎている" [basic.compound]/3は++ptrが次のboolを「指し示している」と言うように見えますが、カチオンは実際には同じアドレスを持ちます。

構文はC++ 11で少し簡単になり、あなたがmake_boolishを必要としない...

#include <vector> 
#include <assert.h> 

struct boolish { bool value; }; 

int main() 
{ 
    std::vector<boolish> vec(10); 
    vec.push_back(boolish{true}); 
    bool* ptr = &vec.front().value; 
    assert(ptr[10] == true); 
    ptr[3] = true; 
    assert(vec[3].value == true); 

    static_assert(sizeof(boolish) == sizeof(bool), ""); 
    boolish test[10]; 
    static_assert(sizeof(test) == (sizeof(bool)*10), ""); 
} 
+0

あなたの提案をお寄せいただきありがとうございますが、私はいくつかの質問があります。まず、私は安全にbool *としてポインタを作ることができますか?隠しパッドはありませんか?第二に、私の質問は、私が掲示した具体的な回避策が機能するかどうかについてです。ありがとう。 –

+0

@NeilKirk、答えは 'basic_string ' –

+0

の私の考えで更新されましたboolish構造体にいくつかの "演算子bool"関数を追加することはできません。 –

3

すべてジョナサン・ウィークリーは語りました。

しかし、私は単純に行くだろう:
私が使用する :

assert(sizeof(bool) == sizeof(char)); 
typedef std::vecor<char> vector_bool; // Now all the rest of your code works as expected 
             // without the need for a maker function. 
+1

'sizeof(bool)== sizeof(char)'を指定すると、標準で保証されていません。しかし、通常、実際にはそうであるはずです。 –

1

"ワーキングドラフトC++、2012年11月2日"

21.1一般的な[strings.general]から
1この節では、任意の非アレイPOD(3.9)タイプのシーケンスを操作するためのコンポーネントについて説明します。

21.4.1のbasic_string一般的な要件は、[string.require]のbasic_stringオブジェクト内
5チャー状オブジェクトが連続して格納されなければなりません。つまり、任意のbasic_stringオブジェクト オブジェクトの場合、ID & *(s.begin()+ n)== & * s.begin()+ nは、0のすべての値に対して保持されます。 < = n < 。サイズ()。

しかし

6参照、ポインタ、反復子それのbasic_stringオブジェクトの以下の使用によって無効にすることができるのbasic_string配列の要素を参照:
- 任意の標準ライブラリへの引数としてconst [operator]、at、front、back、begin、rbegin、end、およびrendを除く非constメンバ関数を呼び出します。

だから、あなたはあなたがどこか他の生の配列を使用しながら、これらの関数を呼び出すことではない、限り、あなたは注意を払うように安全でなければなりません。

更新

文字の特徴及び要件は21.2文字の特徴[char.traits]21.2.1文字の特徴要件[char.traits.require]に記載されています。さらに、typedefとspecializationは21.2.2の特性typedef [char.traits.typedefs]21.2.3 char_traits specializations [char.traits.specializations]にそれぞれ記述されています。

これらの形質は、入出力ライブラリでも使用されます。したがって、eof()またはpos_typeoff_typeのような要件がありますが、これはbasic_stringのコンテキストでは意味がありません。

私はcharchar16_tchar32_twchar_tための4つの専門分野以外にも、実際にimplementatinによって定義されるべきこれらの特性のためにどのような要件が表示されません。それはあなたの例ではgcc 4.7で箱から出して働いていた、が

は、私が提供するデフォルトの実装を(GCC 4.7)取っただけ

struct bool_traits { 
    typedef bool char_type; 
    static void assign(char_type &r, char_type d); 
    static char_type *copy(char_type *s, const char_type *p, std::size_t n); 
    static char_type *move(char_type *s, const char_type *p, std::size_t n); 
}; 

を最小限bool_traitsを定義し、使用されたもの

のような
std::basic_string<bool, bool_traits> ab; 

ご使用の環境によっては、すでに実装されている可能性があります。そうでない場合は、簡単にbool_traitsまたはテンプレートの特殊化std::char_traits<bool>を実装することができます。

Working Draft, PDFまたはcppreference.com - std::char_traitsに文字特性の完全なインターフェイスが表示されます。

+2

dequeは、私が知る限りすべての要素が連続していることを保証するものではありません。また、提案されたソリューションが機能するかどうかにのみ関心があります。ありがとう。 –

+1

ランダムアクセスイテレータは、すべての要素が連続しているわけではありませんが、連続したものではなく、複数の連続したブロックを取得するように「ページ」に格納します。したがって、配列を期待するものに渡すことはできません。 'vector'と' basic_string'だけが連続した記憶域を保証します –

+0

@JonathanWakelyあなたが正しいです、両端キューに連続したメモリは言及されていません。 –

関連する問題