解决vector <bool>的问题,使用basic_string <bool>?</bool> </bool>

时间:2013-03-07 14:38:06

标签: c++

这是一个安全的解决方法吗?我想使用 vector bool 但是需要传递指向期望C风格数组的旧代码的指针。

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;
}

编辑: 感谢您提供其他解决方案的建议,但我真的希望对上述解决方案有一个明确的答案。感谢。

4 个答案:

答案 0 :(得分:15)

我不确定std::basic_string<bool>因为那会实例化std::char_traits<bool>而我不确定标准是否需要定义,或者char_traits主模板是否可以left undefined,只定义了char_traits<char>等明确的特化。您不能提供自己的char_traits<bool>专业化,因为如果专业化取决于用户定义的类型,bool显然不是,那么您只能专门化标准模板。也就是说,如果您的stdlib确实具有默认的char_traits定义,并且您不尝试使用需要char_traits成员执行任何有用的字符串操作,那么它可能会有效。

或者,这很hacky但可能会有效:

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数组具有相同的表示形式(您需要检查编译器,我使用static_assert检查没有填充)然后你可能会使用它,虽然它可能违反了别名规则,因为*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), "" );
}

答案 1 :(得分: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.

答案 2 :(得分:1)

来自“Working C ++,2012-11-02”

  

21.1一般[strings.general]
  1本条款描述了用于操纵任何非阵列POD(3.9)类型序列的组件。

     

21.4.1 basic_string一般要求[string.require]
  5 basic_string对象中类似char的对象应连续存储。也就是说,对于任何basic_string   对象s,身份&amp; *(s.begin()+ n)==&amp; * s.begin()+ n应保留n的所有值,使得0   &lt; = n&lt; s.size()。

但是

  

6引用basic_string序列元素的引用,指针和迭代器可能会被该basic_string对象的以下用法无效:
   - 作为任何标准库函数的参数,将非const basic_string作为参数引用.233
   - 调用非const成员函数,除了operator [],at,front,back,begin,rbegin,end和rend。

所以,只要你注意不要调用这些函数,你就应该安全,而在其他地方使用原始数组。

<强>更新

字符特征和要求在 21.2 Character traits [char.traits] 21.2.1 Character traits requirements [char.traits.require] 中描述。此外,typedef和specializations分别在 21.2.2 traits typedefs [char.traits.typedefs] 21.2.3 char_traits specializations [char.traits.specializations] 中描述。 / p>

这些特征也用于输入/输出库。因此,eof()pos_typeoff_type等要求在basic_string的背景下没有意义。

除了charchar16_tchar32_twchar_t的四个专业之外,我认为实际上并没有要求实施这些特征。

虽然它与你的例子一起使用gcc 4.7开箱即用,我只用

定义了一个最小bool_traits
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);
};

采用了提供的默认实现(gcc 4.7),并使用了

std::basic_string<bool, bool_traits> ab;

您的环境可能已经提供了有效的实施方案。如果没有,您可以自己实施简单的bool_traits或模板专业化std::char_traits<bool>

您可以在Working Draft, PDFcppreference.com - std::char_traits中看到完整的角色特征界面。

答案 3 :(得分:1)

您也可以使用 boost::container::vector。它与 std::vector 完全一样,但不是专门用于 bool

相关问题