简体   繁体   English

std :: vector <MyObj *>到std :: vector <MyObj Const *>,如何没有循环?

[英]std::vector< MyObj* > to std::vector< MyObj Const * >, how to no loops?

Title, 标题,

Let say we have 让我们说

std::vector<MyObj*> ArrayOfPtr;

std::vector<MyObj const *> ArrayOfPtrToConstObj;

int main()
{
     //I'd like to give ArrayOfPtr to another obj/function but not give it the right to modify the objects in it.

    ArrayOfPtrToConstObj = ArrayOfPtr;

    Function(ArrayOfPtrToConstObj)
}

Why can't that be written in C++ and understood automatically by the compiler considering const does not alter the logic (optimization or anything)..? 为什么不能用C ++编写并且编译器自动理解,考虑到const不会改变逻辑(优化或任何东西)..?

Is there a quick way to go from vector 1 to vector 2 without having to for/while loop onto the array and fill the second one? 有没有一个快速的方法从矢量1到矢量2而不必for / while循环到阵列上并填充第二个?

Well, someone, somewhere is going to have to loop. 好吧,有人,某个地方将不得不循环。 You can avoid writing the loop yourself by using vector::assign : 您可以使用vector::assign避免自己编写循环:

ArrayOfPtrToConstObj.assign(ArrayOfPtr.begin(), ArrayOfPtr.end());

But assign is still going to loop. assign仍然会循环。

The preferred modern solution is to either pass an const-iterator/pointer pair and let the user consume them, or to use a view class like gsl::span . 首选的现代解决方案是传递一个const-iterator / pointer对,让用户使用它们,或者使用像gsl::span这样的视图类。 This requires no copying of anything, and can add const as needed: 这不需要复制任何东西,并且可以根据需要添加const

gsl::span<MyObj const*> spn(ArrayOfPtr.data(), ArrayOfPtr.size());

vector2 is a fundamentally different type. vector2是一种根本不同的类型。 If, however, you just want to view the inside of vector1 in a const manner, I have a solution for you. 但是,如果您只想以const方式查看vector1的内部,我可以为您提供解决方案。

I'd start with something like, but not exactly, gsl::span . 我会从像gsl::span这样的东西开始。

template<class T>
struct span {
private:
  T* b = 0;
  T* e = 0;
public:
  T* begin() const { return b; }
  T* end() const { return e; }
  T* data() const { return begin(); }

  template<class U>
  using compatible = std::enable_if_t< std::is_convertible< U*, T* >{} && sizeof(T)==sizeof(U), bool >;

  template<class U,
    compatible<U> =true
  >
  span( U* s, U* f ): b(s), e(f) {}
  template<class U,
    std::enable_if_t< std::is_convertible< U*, T* >{} && sizeof(T)==sizeof(U), bool > =true
  >
  span( U* s, std::size_t length ): span( s, s+length ) {}

  // pointer semantics:
  span()=default;
  span(span const&)=default;
  span& operator=(span const&)=default;
  ~span()=default;         

  std::size_t size() const{ return end()-begin(); }
  bool empty() const{ return end()==begin(); }
  T& front() const { return *begin(); }
  T& back() const { return *(end()-1); }

  // sub spans:
  span without_front( std::size_t n=1 ) const {
    n = (std::min)(n, size());
    return {begin()+n, end()};
  }
  span without_back( std::size_t n=1 ) const {
    n = (std::min)(n, size());
    return {begin(), end()-n};
  }
  span only_front( std::size_t n=1 ) const {
    n = (std::min)(n, size());
    return {begin(), begin()+n};
  }
  span only_back( std::size_t n=1 ) const {
    n = (std::min)(n, size());
    return {end()-n, end()};
  }
  span sub( std::size_t start, std::size_t length ) const {
    return without_front(start).only_front(length);
  }
  T& operator[](std::size_t I)const{ return begin()[I]; }
  T& at(std::size_t I)const{
     if (I>=size()) throw std::out_of_range{"index"};
     return begin()[I];
  }
  std::vector<std::decay_t<T>> as_vector()const& {
    return {begin(), end()};
  }
  std::vector<std::decay_t<T>> as_vector()&& {
    return {std::make_move_iterator(begin()), std::make_move_iterator(end())};
  }
  template<class C,
    compatible< std::decay_t< decltype( *std::declval<C&>().data() ) > > =true,
    std::enable_if_t< !std::is_same<span, std::decay_t<C>>{}, bool > =true
  >
  span( C&& c ): span(c.data(), c.size()) {}
};

If you do not intend to change the length of a vector in a context, a span is the right answer. 如果您不打算在上下文中更改vector的长度,则span是正确的答案。

Live example with some tests. 一些测试的实例

Function in this case should take span< MyObj const*const > , stating it just wants to look at a buffer of MyObj const s. 在这种情况下的Function应该采用span< MyObj const*const > ,声明它只是想查看MyObj const的缓冲区。 You can store a span of this type if you want to, or let implicit conversion work: 如果您愿意,可以存储此类型的范围,或者让隐式转换工作:

std::vector<MyObj*> ArrayOfPtr;

span<MyObj const*const> SpanOfPtrToConstObj;

int main()
{
  //I'd like to give ArrayOfPtr to another obj/function but not give it the right to modify the objects in it.

  SpanOfPtrToConstObj = ArrayOfPtr;

  Function(SpanOfPtrToConstObj)
}

Function cannot modify the length of the vector or the pointers within it or what the pointers point to. Function不能修改向量的长度或其中的指针或指针指向的长度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM