boost::span 能与 boost::begin 一起正常工作吗?

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

我正在使用 Boost 1.78,并且我正在尝试使用它的

std::span
实现。虽然 Span 实现似乎很好,但当我在 Span 上调用
boost::begin()
时,如果该 Span 是右值,它会返回一个 const 指针,这会破坏重要的用例,例如:

   boost::fill( returns_a_span(), 0 );

测试程序(无法编译 - 有趣的是错误消息)是:

#include <vector>
#include <boost/core/span.hpp>
#include <boost/range/begin.hpp>

template <typename T>
struct ErrorType;

int main() {

   std::vector<unsigned char> vec{ 1, 2, 3, 4, 5 };
   boost::span<unsigned char> sp{ vec };

   ErrorType< decltype( std::begin(sp) ) > e1;
   ErrorType< decltype( std::begin(std::move(sp)) ) > e2;
   ErrorType< decltype( boost::begin(sp) ) > e3;
   ErrorType< decltype( boost::begin(std::move(sp)) ) > e4;
   ErrorType< decltype( sp.begin() ) > e5;
   ErrorType< decltype( std::move(sp).begin() ) > e6;

   return 0;
}

编译器的输出是:

spantest.cc: In function int main():
spantest.cc:13:44: error: aggregate ErrorType<unsigned char*> e1 has incomplete type and cannot be defined
    ErrorType< decltype( std::begin(sp) ) > e1;
                                            ^~
spantest.cc:14:55: error: aggregate ErrorType<unsigned char*> e2 has incomplete type and cannot be defined
    ErrorType< decltype( std::begin(std::move(sp)) ) > e2;
                                                       ^~
spantest.cc:15:46: error: aggregate ErrorType<unsigned char*> e3 has incomplete type and cannot be defined
    ErrorType< decltype( boost::begin(sp) ) > e3;
                                              ^~
spantest.cc:16:57: error: aggregate ErrorType<const unsigned char*> e4 has incomplete type and cannot be defined
    ErrorType< decltype( boost::begin(std::move(sp)) ) > e4;
                                                         ^~
spantest.cc:17:40: error: aggregate ErrorType<unsigned char*> e5 has incomplete type and cannot be defined
    ErrorType< decltype( sp.begin() ) > e5;
                                        ^~
spantest.cc:18:51: error: aggregate ErrorType<unsigned char*> e6 has incomplete type and cannot be defined
    ErrorType< decltype( std::move(sp).begin() ) > e6;

类型不完整这一事实是预料之中的——我只是用它作为让编译器告诉我类型是什么的一种方式。有趣的是 e4 - 右值跨度上的

boost::begin()
返回一个 const 指针,即使该方法不返回 (e6) 且
std::begin()
不返回 (e2)。这只是
boost::begin()
中的一个错误,还是我误解了什么?除了始终使用左值之外,还有其他解决方法吗?

看起来这个问题与std::begin和R-values密切相关,但

std::begin()
似乎不再有问题,但
boost::begin()
有。然而,提升范围算法显式调用
boost::begin()
,因此它们似乎不适用于非常量数据的跨度。

我理解,如果使用右值调用

boost::begin()
并且不存在右值重载,则它可以使用 const 左值引用。我不明白的是为什么
boost::span
与任何其他迭代器范围不同 - boost 范围算法始终传递右值范围,但我以前从未见过这一点。

c++ boost
1个回答
0
投票

看起来整个问题是您正在实例化不完整的

ErrorType
实例。

为了简洁起见,让我们将其重命名为

E
并实际定义它!

template <typename> struct E{};

现在一切都编译好了:https://godbolt.org/z/E78qh8c75

#include <boost/core/span.hpp>
#include <boost/range/begin.hpp>
#include <vector>

template <typename> struct E{};

int main() {
    std::vector<unsigned char> vec{1, 2, 3, 4, 5};
    boost::span<unsigned char>   sp{vec};

    E<decltype(std::begin(sp))>              e1;
    E<decltype(std::begin(std::move(sp)))>   e2;
    E<decltype(boost::begin(sp))>            e3;
    E<decltype(boost::begin(std::move(sp)))> e4;
    E<decltype(sp.begin())>                  e5;
    E<decltype(std::move(sp).begin())>       e6;
}
© www.soinside.com 2019 - 2024. All rights reserved.