Если я вас правильно понял, вы хотите измерение времени компиляции, но экстенты времени выполнения.
Я бы использовал такой дизайн:
template <typename T,std::size_t Dim>
class mdvector
{
private:
std::vector<T> Data;
std::array<std::size_t,Dim> Extents;
private:
std::size_t Offset(std::size_t const Sum) const
{ return Sum; }
template <typename... IndexType>
std::size_t Offset(std::size_t const Sum,std::size_t const Index,IndexType const... Indices) const
{ return Offset(Sum*Extents[Dim-sizeof...(Indices)-1u]+Index,Indices...); }
public:
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
mdvector(IndexType const... Indices):
Data((... * Indices)), // c++17 fold expression
Extents{Indices...} {}
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
T const &operator()(IndexType const... Indices) const
{ return Data[Offset(0u,Indices...)]; }
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
T &operator()(IndexType const... Indices)
{ return Data[Offset(0u,Indices...)]; }
};
Данные хранятся вstd::vector
, в то время как экстенты составляют std::array
.
Поскольку я предполагаю, что вам нужен многомерный доступ, я использовал данное отображение через рекурсивную функцию Offset
.У вас есть полная свобода в этом отношении.
Вот пример использования:
int main()
{
mdvector<double,3u> myvec(2u,3u,4u);
for (int i= 0; i<2; ++i)
for (int j= 0; j<3; ++j)
for (int k= 0; k<4; ++k)
myvec(i,j,k)= i;
for (int k= 0; k<4; ++k)
{
for (int i= 0; i<2; ++i)
{
for (int j= 0; j<3; ++j)
std::cout << myvec(i,j,k) << "\t";
std::cout << "\n";
}
std::cout << "\n";
}
}
Поскольку экстенты являются динамическими, вы можете изменить их во время выполнения, например:
template <typename T,std::size_t Dim>
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
void mdvector<T,Dim>::Resize(IndexType const... Indices)
{ Data.resize((... * Indices)); Extents= {Indices...}; }
Если, с другой стороны, вы предпочитаете, чтобы экстенты были параметрами шаблона, они должны оставаться фиксированными во время выполнения.В этом случае вы бы включили их в объявление класса:
template <typename T,std::size_t... Indices>
class mdvector { /* ... */};
, но реализация была бы почти такой же.Обратите внимание, что указание размера не требуется, поскольку вы можете получить его с помощью sizeof...(Indices)
.
. Выражение сгиба в приведенном выше коде не является обязательным.Эквивалентный результат достигается с помощью:
static constexpr std::size_t Product()
{ return 1u; }
template <typename... IndexType>
static constexpr std::size_t Product(std::size_t const Index,IndexType const... Indices)
{ return Index*Product(Indices...); }
template <typename... IndexType,typename= std::enable_if_t<sizeof...(IndexType)==Dim>>
mdvector(IndexType const... Indices):
Data(Product(Indices...)), Extents{Indices...} {}