LoginSignup
0
2

More than 5 years have passed since last update.

std::vectorから一定間隔で各要素へのポインタを取得する

Last updated at Posted at 2017-04-01

やりたいこと

元々は,二次元配列を使用しているコードが既にあった時に,できるだけクライアントコードの変更を少なくしつつ,一次元配列によるエミュレートに入れ変えたかった.
例えば,int64_t a[N][M];みたいな定義があった時に,aを関数に渡したり,a[i][j]で参照したりしているので,これら構文に対応しつつ,エミュレートするようなクラスの型にaを変える.

いわゆるwork aroundのコードなので,正直に言って,bad know-howな気がする.
あまり真似しない方が良いと思う.

アドホックにコードを書くのは面倒なので,std::vectorは多くの場合において用意できることが期待できるので,これがあった時,一定の間隔で各要素へのポインタの列を取り出すコードを書くことにした.

コード

#include <iostream>
#include <vector>
#include <cstdint>

#include <boost/range/algorithm/copy.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/transformed.hpp>

namespace impl {
template<class OutVec, class InVec>
void getPtrs(OutVec& ovec, InVec& vec, const int step = 1) {
    auto getPtr = [&](auto x) { return vec.data() + x; };
    boost::copy(boost::irange(static_cast<decltype(vec.size())>(0), vec.size())
        | boost::adaptors::transformed(std::ref(getPtr))
        | boost::adaptors::strided(step),
        std::back_inserter(ovec));
}
}

template<class T>
auto getPtrs(const std::vector<T>& vec, const int step = 1) {
    using ptr_type = typename std::add_pointer<typename std::add_const<T>::type>::type;
    std::vector<ptr_type> ptrs;
    impl::getPtrs(ptrs, vec, step);
    return ptrs;
}

template<class T>
auto getPtrs(std::vector<T>& vec, const int step = 1) {
    using ptr_type = typename std::add_pointer<T>::type;
    std::vector<ptr_type> ptrs;
    impl::getPtrs(ptrs, vec, step);
    return ptrs;
}

int main() {
    {
        auto ir = boost::irange(0, 100);
        const std::vector<uint64_t> a(boost::begin(ir), boost::end(ir));
        auto b = getPtrs(a, 16);
        boost::copy(b, std::ostream_iterator<decltype(b)::value_type>(std::cout, " "));
        std::cout << std::endl;
        for (auto&& x : b) {
            std::cout << x << " = " << *x << std::endl;
        }
        std::cout << b[2][5] << std::endl;
    }
    std::cout << std::endl;
    {
        auto ir = boost::irange(0, 100);
        std::vector<uint64_t> a(boost::begin(ir), boost::end(ir));
        auto b = getPtrs(a, 16);
        boost::copy(b, std::ostream_iterator<decltype(b)::value_type>(std::cout, " "));
        std::cout << std::endl;
        for (auto&& x : b) {
            std::cout << x << " = " << *x << std::endl;
        }
        std::cout << b[3][4] << std::endl;
        b[3][4] = 10;
        std::cout << b[3][4] << std::endl;
    }
}
0
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2