无法从 `const std::vector<T>&`<T> 构造 `std::span

问题描述 投票:0回答:2

考虑以下代码:

std::vector<float> foo = some_generator_function();
std::span<float> bar {foo};
/* Wrapper for C API that uses bar->data() and bar->size_bytes()
 * if bar != nullptr, guaranteed not to change any data in bar.
 * In some cases bar is constructed from a const C array.
 */
do_smth (&bar);

此代码编译并运行良好,因为

std::span
可以从
std::vector
构造。

现在,我正在尝试将其包装成一个单独的函数:

void do_wrap (const std::vector<float>& foo) {
        std::span<float> bar (foo);
        do_smth (&bar);
}

问题就出现了:

错误:没有匹配的函数可用于调用 'std::span::span(const std::vector&)'`

更准确地说,

const std::vector<float>&
不满足约束条件。

这有什么原因吗?我现在怀疑

const
限定符。

构建为

bar (foo.data(), foo.size())
会报告类似的错误。

使用 g++ 14.2.0、MinGW64 编译。

c++ c++20 stdvector std-span
2个回答
3
投票

您无法修改

const std::vector<float>&
元素,但可以修改
std::span<float>
元素,因此两者不兼容。

您应该使用

std::span<const float>
来代替。


旁注:

std::span
是一种轻量级传值类型(它是一个指针和一个大小),您可以将其按值传递给函数。

void do_smth(std::span<const float> arg);

void do_wrap (const std::vector<float>& foo) 
{
  do_smth(bar); // implicitly constructs std::span<const float>
}

如果您正在与 C API 交互,那么最好更新 C API 以期望

const float*
做出不显式修改数据的承诺,但如果您无法修改它,那么您可以使用
const_cast
在 C API 边界的
do_smth
内部,丢弃 const 的风险由您自行承担。如果该函数实际上修改了数据,那么您就有未定义的行为。


2
投票

您可以将

do_wrap
写为
span
作为参数,并传递
vector
作为参数。如果您需要重复进行转换,您可能需要使用这个版本的
do_wrap
,它也说明了该技术。

注意:另一个答案是在我写我的文章时发布的。如果 C 函数需要

const
,您可以返回
const span
。我修改了代码来演示这一点。

#include <span>
#include <vector>

#include <fmt/ranges.h>
using fmt::println, fmt::print;

// convert vector to span    
auto do_wrap(const std::span<float>& meow) -> const std::span<float> {
   return meow;
}

auto main() -> int {
   std::vector<float> meow{1, 2, 3};

   auto woof {do_wrap(meow)};
   println("{}", woof);
   return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.