やりたいこと
元々は,二次元配列を使用しているコードが既にあった時に,できるだけクライアントコードの変更を少なくしつつ,一次元配列によるエミュレートに入れ変えたかった.
例えば,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;
}
}
- Wandbox上のコード: https://wandbox.org/permlink/QmqljLS5S9uNCScA