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

时间:2019-05-06 08:51:42

标签: c++ boolean stdvector hpc

我正在处理无法更改数据类型的库。我需要调用一个使用bool数组的函数。我正在使用的代码使用std::vector<bool>来存储布尔值。我已经阅读了很多关于std::vector<bool>以及SO相关问题的信息,但是我还没有找到解决我问题的最优雅的解决方案。这是性能至关重要的代码。如何以最有效的方式处理此问题?我可以更改存储在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, %d\n", 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;
}

3 个答案:

答案 0 :(得分:5)

您知道该怎么做...创建临时布尔数组并复制值。

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());

答案 1 :(得分:2)

  

我可以更改存储在std::vector中的类型,但是我无法转义   使用std::vector

在这种情况下,您很不走运。 std::vector<bool>不存储布尔数组,其data()也不返回指向布尔数组的指针(就像所有其他std::vectors对其各自的数据类型一样)。

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

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

答案 2 :(得分:0)

我尝试使用您的示例使其工作,并且以下(相当脏的)解决方案运行良好:

#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]?"true\n":"false\n");
    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:正确
  1:错误
  2:错误
  3:是的
  4:错误

  0:是的
  1:错误
  2:错误
  3:是的
  4:错误

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

事实上,如果我们可以保证sizeof(bool) == sizeof(uint8_t)并假设truefalse在内存中分别被视为整数10,解决方案将起作用,但不能成功。

我希望它能提供帮助。

编辑:用uint8_t类型替换了char


EDIT2:

另一种不违反严格别名规则的解决方案是 Kamil Cuk 提到的一种解决方案,即创建一个Bool包装器并仍然检查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());

对我有用:)