この種の状況のために独自のクラスを作成することになりました。行列操作ライブラリが行列をデータの連続ブロックとして受け取ることは非常に一般的ですが、同時に、標準の m[i][j] アクセサーを使用してそれを埋めて読み取ることができるようにしたいと考えています。では、どうぞ。以下は、メモリの連続ブロックとして任意の次元でコンテナーを作成するコードです。ここでブースト プリプロセッサを使用して、任意のディメンションを実行できるようにします。3Dまでしか必要ない場合は、ブーストを解除するのは明らかです:)
memblock.h
#ifndef BOOST_PP_IS_ITERATING
#ifndef MEMBLOCK_INCLUDED
#define MEMBLOCK_INCLUDED
#include <algorithm>
#include <boost/preprocessor.hpp>
# ifndef MBLOCK_MAX_DIM
# define MBLOCK_MAX_DIM 4
# endif
template <typename T> class MemoryBlock1d
{
protected:
T* m_data;
public:
MemoryBlock1d() { m_data = 0; }
MemoryBlock1d(int size) { m_data = 0; resize(size); }
MemoryBlock1d(int size, T val) { m_data = 0; resize(size, val); }
virtual ~MemoryBlock1d();
inline T*& data() { return m_data; }
inline void resize(int size);
inline void resize(int size, T val);
inline void clear();
inline T& operator[](int i) { return m_data[i]; }
};
// Implementation 1d:
template <typename T> inline MemoryBlock1d<T>::~MemoryBlock1d()
{
if (m_data)
{
delete[] m_data;
}
}
template <typename T> inline void MemoryBlock1d<T>::clear()
{
if (m_data)
{
delete[] m_data;
}
m_data = 0;
}
template <typename T> inline void MemoryBlock1d<T>::resize(int size)
{
if (m_data)
{
delete[] m_data;
}
m_data = new T[size];
}
template <typename T> void MemoryBlock1d<T>::resize(int size, T val)
{
resize(size);
std::fill(m_data, m_data + size, val);
}
// generate multi_dimensional blocks:
# define BOOST_PP_ITERATION_LIMITS (2, MBLOCK_MAX_DIM)
# define BOOST_PP_FILENAME_1 "memblock.h" // this file
# include BOOST_PP_ITERATE()
#endif // MEMBLOCK_INCLUDED
#else // BOOST_PP_IS_ITERATING
# define n BOOST_PP_ITERATION()
# define nprev BOOST_PP_SUB(n, 1)
# define MemoryBlockNd BOOST_PP_CAT(MemoryBlock, BOOST_PP_CAT(n, d))
# define MemoryBlockPREVd BOOST_PP_CAT(MemoryBlock, BOOST_PP_CAT(nprev, d))
# define MB_print(z, m, data) data
# define MB_timesDATAM(z, m, data) * BOOST_PP_CAT(data, m)
template <typename T> class MemoryBlockNd : public MemoryBlock1d<T>
{
private:
MemoryBlockPREVd<T*> m_pointers;
public:
MemoryBlockNd() { MemoryBlock1d<T>::data() = 0; }
MemoryBlockNd(BOOST_PP_ENUM_PARAMS(n, int size)) { MemoryBlock1d<T>::data() = 0; resize(BOOST_PP_ENUM_PARAMS(n, size)); }
MemoryBlockNd(BOOST_PP_ENUM_PARAMS(n, int size), T val) { MemoryBlock1d<T>::data() = 0; resize(BOOST_PP_ENUM_PARAMS(n, size), val); }
inline void resize(BOOST_PP_ENUM_PARAMS(n, int size));
inline void resize(BOOST_PP_ENUM_PARAMS(n, int size), T val);
inline T BOOST_PP_REPEAT(nprev, MB_print,*) & operator[](int i) { return m_pointers[i]; }
};
// Implementation n-dim:
template <typename T> void MemoryBlockNd<T>::resize(BOOST_PP_ENUM_PARAMS(n, int size))
{
m_pointers.resize(BOOST_PP_ENUM_PARAMS(nprev, size));
int sizePointers = size0 BOOST_PP_REPEAT_FROM_TO(1, nprev, MB_timesDATAM, size);
int sizeData = sizePointers * BOOST_PP_CAT(size, nprev);
MemoryBlock1d<T>::resize(sizeData);
T *p = MemoryBlock1d<T>::data();
T **ptr = m_pointers.data();
for (int i=0; i < sizePointers; i++, p += BOOST_PP_CAT(size, nprev)) ptr[i] = p;
}
template <typename T> void MemoryBlockNd<T>::resize(BOOST_PP_ENUM_PARAMS(n, int size), T val)
{
resize(BOOST_PP_ENUM_PARAMS(n, size));
int sizeData = size0 BOOST_PP_REPEAT_FROM_TO(1, n, MB_timesDATAM, size);
std::fill(MemoryBlock1d<T>::data(), MemoryBlock1d<T>::data() + sizeData, val);
}
# undef MB_timesDATAM
# undef MB_print
# undef MemoryBlockPREVd
# undef MemoryBlockNd
# undef nprev
# undef n
#endif // BOOST_PP_IS_ITERATING
memblock.cpp
// test the class here
#include <stdio.h>
#include <memblock.h>
int main() {
MemoryBlock3d<double> cube(2, 2, 2);
double *p = &cube[0][0][0];
for (int i=0; i < 8; i++)
p[i] = 0.5 + i;
for (int i=0; i < 2; i++)
for (int j=0; j < 2; j++)
for (int k=0; k < 2; k++)
printf("%f\n", cube[i][j][k]);
return 0;
}