簡體   English   中英

將std :: vector轉換為另一個std :: vector

[英]Cast std::vector as another std::vector

我需要將三角形的向量轉換為索引的三次較長的向量:

struct Triangle { int16_t v[3] };

std::vector<Triangle>
std::vector<int16_t>

也許我可以從封裝的原始內存中以某種方式轉換已初始化向量的迭代器?

編輯:是的,我不要任何副本。

你不能這樣做。

但是,您可以這樣做:

std::vector<Triangle> ts;
__int16 *pvbegin = ts[0].v;
__int16 *pvend = pvbegin + 3 * ts.size();

並使用pvbeginpvend對作為迭代器范圍。

我不確定這不是技術上的不確定行為,但是應該可以正常工作。 確保在某個地方添加static_assert是一個好主意,例如:

static_assert(sizeof(Triangle) == 3*sizeof(int16_t), "Weird sizeof(Triangle)");

您是在尋找一種明智的方法,還是只是一種可行的方法?

std::vector<int16_t> vec_int;
std::vector<Triangle> vec_tri;
for (const auto& tri : vec_tri)
{
    for (int i = 0; i < 3; i++)
    {
        vec_int.push_back(tri.v[i]);
    }
}

大編輯:這似乎是正確且容易的(全部經過測試)

static_assert(sizeof(Triangle) == 3*sizeof(int16_t),
    "Weird sizeof(Triangle)");
struct SimpleWrapper {
private:
    std::vector<Triangle>& vect;
public:
    SimpleWrapper(std::vector<Triangle>& vect)
    : vect(vect) {
    }
    int16_t* begin() {
        return vect[0].v;
    }
    int16_t* end() {
        return begin() + vect.size()*3;
    }
};

原版的:

#include <vector>
#include <iostream>

struct Triangle { int16_t v[3]; };

struct Iterator: std::iterator<
  std::input_iterator_tag,
  int16_t> {
private:
    std::vector<Triangle>& vect;
    int index, subidx;
public:
    Iterator(
      std::vector<Triangle>& vect,
      int index, int subidx)
    : vect(vect), index(index), subidx(subidx) {
    }
    Iterator(const Iterator& src)
    : vect(src.vect), index(src.index), subidx(src.subidx) {
    }
    Iterator& operator++() {
        if(++subidx == 3) {
            subidx = 0; index++;
        }
        return *this;
    }
    Iterator operator++(int) {
        Iterator tmp(*this);
        operator++();
        return tmp;
    }
    bool operator==(const Iterator& rhs) {
        return &rhs.vect == &vect
          && rhs.index == index
          && rhs.subidx == subidx;
    }
    bool operator!=(const Iterator& rhs) {
        return !(*this == rhs);
    }
    int16_t& operator*() {
        return vect[index].v[subidx];
    }
};

struct Wrapper {
private:
    std::vector<Triangle>& vect;
public:
    Wrapper(std::vector<Triangle>& vect)
    : vect(vect) {
    }
    Iterator begin() {
        return Iterator(vect, 0, 0);
    }
    Iterator end() {
        return Iterator(vect, vect.size(), 0);
    }
};

int main() {
    std::vector<Triangle> vect;
    vect.push_back(Triangle { 1,2,3 });
    vect.push_back(Triangle { 6,7,8 });

    Wrapper wrap(vect);
    for (int16_t v : wrap)
        std::cout << v << ' ';
}

絕對不是,因為訪問向量的“長度”幾乎肯定是錯誤的。 可能還有其他不透明的實現細節也會出錯。 充其量,您也許可以投射:

#include <type_traits>
...
static_assert(sizeof(Triangle) == (sizeof(int16_t) * 3) &&
              std::is_standard_layout<Triangle>::value),
              "Triangle does not satisfy contiguous storage requirements");

// i-th triangle from: std::vector<int16_t> values
Triangle *t = reinterpret_cast<Triangle *>(& values[i * 3]);

該標准並未對reinterpret_cast做出很多保證。

如果您只真正關心如何訪問數據,而不是真正關心數據是否存儲在std::vector<int16_t> ,則可以使自己的迭代器按順序遍歷頂點。 如果迭代器當前位於三角形的第一個頂點,則將其遞增將帶您到第二個頂點; 從第二個頂點開始,遞增會帶您到第三個頂點; 從第三個頂點開始,遞增將為您提供下一個三角形的第一個頂點。

您還可以制作一個對象,該對象提供對三角形頂點的“隨機訪問”,並輸入從0到number_of_triangles-1(含)之間的數字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM