将 std::vector<bool> 传递给外部函数

Passing std::vector<bool> to an external function

本文关键字:外部 函数 gt std lt bool vector      更新时间:2023-10-16

我正在处理一个我无法更改数据类型的库。我需要调用采用bool数组的函数。我与之合作的代码使用std::vector<bool>存储bool。我已经阅读了很多有关std::vector<bool>和相关问题的信息,但是我还没有找到解决问题的最优雅解决方案。这是性能至关重要的代码。如何以最有效的方式处理这个问题?我可以更改std::vector中存储的类型,但是我无法逃脱使用std::vector

在我自己的问题中,我必须调用fortran函数,但是我在C 中做了一个最小的示例来说明问题。

#include <cstdio>
#include <vector>
void print_c_bool(bool* bool_array, size_t n)
{
    for (int i=0; i<n; ++i)
        printf("%d, %dn", i, bool_array[i]);
}
int main()
{
    // This works.
    bool bool_array[5] = {true, false, false, true, false};
    print_c_bool(bool_array, 5);
    // This is impossible, but how to solve it?
    std::vector<bool> bool_vector {true, false, false, true, false};
    // print_c_bool(bool_vector.data(), bool_vector.size());
    return 0;
}

您知道要做什么...创建一个临时的布尔并复制值。

auto v = new bool[bool_vector.size()];
std::copy(bool_vector.begin(), bool_vector.end(), v);
print_c_bool(v, bool_vector.size());
delete[] v;

auto v = std::make_unique<bool>(bool_vector.size());
std::copy(bool_vector.begin(), bool_vector.end(), v.get());
print_c_bool(v.get(), bool_vector.size());

我可以更改std::vector中存储的类型,但我无法逃脱 从使用std::vector

在这种情况下,您不幸。std::vector<bool>不存储一系列布尔值,其data()也不会将指针返回到一系列布尔值(就像所有其他std::vectors对其各自的数据类型所做的那样(。

您可以玩一些技巧并使用std::vector<uint8_t>或类似的方法,尽管即使尺寸匹配,uint8_t*也不是bool*!鉴于该函数无法更改,您只能避免通过将数据复制到Bool数组中来违反严格的混杂。

如果您确实在乎性能,那么我建议您考虑不使用std::vector<bool>。例如,您真的需要动态大小吗?如果不使用std::array

我试图使用您的示例和以下(非常脏(的解决方案使其正常工作:

#include <iostream>
#include <vector>
void test_print(bool * arr, size_t s)
{
    for(unsigned int i = 0; i< s; ++i)
        std::cout << i << ": " << (arr[i]?"truen":"falsen");
    std::cout << std::endl;
}
int main()
{
    bool b_arr[5] = {true, false, false, true, false};
    test_print(b_arr, 5);
    //std::vector <uint8_t> b_vec = {true, false, false, true, false}; // former proposal
    std::vector <char> b_vec = {true, false, false, true, false}; // new proposal
    test_print(reinterpret_cast<bool*>(b_vec.data()), b_vec.size());
    return 0;
}

我得到的输出是:

0:true
1:false
2:false
3:true
4:false

0:true
1:false
2:false
3:true
4:false

但是,我不知道它在每个系统/平台上是否会表现相同。但是,如果您不打算更改系统/平台,并且它确实适用于您的系统/平台,那么我认为即使这是一个非常肮脏的解决方案,也可以完成工作。

实际上,如果我们可以保证sizeof(bool) == sizeof(uint8_t)和假设truefalse在内存中分别将其视为整数10,则此解决方案将起作用,但不行。

>

我希望它能有所帮助。

编辑:由char替换uint8_t


edit2:

另一种不违反严格的混叠规则的解决方案是 kamil cuk 提到的是创建一个布尔包装器,并且仍然检查sizeof(bool) == sizeof(Bool)

可能的实现(仅基线代码(可以是:

struct Bool
{
    bool v;
    Bool(bool bv=false) : v(bv)
    {}
};

然后您将能够写:

std::vector<Bool> b_vec {true, false, false, true, false};
test_print(reinterpret_cast<bool*>(b_vec.data()), b_vec.size());

它对我有用:(