8

这是一个安全的解决方法吗?我想使用向量 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

3 回答 3

17

我不确定,std::basic_string<bool>因为它会实例化std::char_traits<bool>,而且我不确定标准是否需要定义它,或者是否char_traits可以保留主模板未定义,只有明确的特化,例如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(你需要检查你的编译器,我用 astatic_assert来检查没有填充),那么你可能会侥幸逃脱,尽管它可能违反了别名规则,因为*ptrand*++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), "" );
}
于 2013-03-07T14:46:09.753 回答
2

来自“C++ 工作草案,2012-11-02”

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

21.4.1 basic_string 一般要求 [string.require]
5 basic_string 对象中的类字符对象应连续存储。也就是说,对于任何 basic_string 对象 s,标识 &*(s.begin() + n) == &*s.begin() + n 应适用于所有 n 值,使得 0 <= n < s.size ()。

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

因此,只要您注意,不要在其他地方使用原始数组时调用这些函数,就应该是安全的。

更新

性格特征和要求在21.2 性格特征 [char.traits]21.2.1 性格特征要求 [char.traits.require]中描述。此外,typedefs 和 specializations 分别在21.2.2 traits typedefs [char.traits.typedefs]21.2.3 char_traits specializations [char.traits.specializations]中描述。

这些特征也用于输入/输出库。所以有些要求,比如eof()orpos_typeoff_type,在basic_string.

除了char、和. char16_t_char32_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>

您可以在工作草案、PDFcppreference.com - std::char_traits中查看角色特征的完整界面。

于 2013-03-07T16:41:19.183 回答
1

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

于 2021-07-31T09:53:19.060 回答