tags:

views:

146

answers:

4

I want to create a vector of vector of a vector of double and want it to already have (32,32,16) elements, without manually pushing all of these back. Is there a way to do it during initialization? (I dont care what value gets pushed)

Thanks

I want a 3 dimensional array, first dimension has 32, second dimension has 32 and third dimension has 16 elements

+1  A: 

One of the ctors for a vector allows you to specify both the size and a value to be copied into the elements for the vector. I'm not quite sure what you means by "(32,32,16)" elements, but you could do something like:

// create a vector containing 16 elements set to 2
std::vector<int> temp(16, 2);   

// create a vector of 32 vectors, each with 16 elements set to 2
std::vector<std::vector<int> > values(32, temp);
Jerry Coffin
I mean I want a 3 dimensional array, first dimension has 32, second dimension has 32 and third dimension has 16 elements
Milo
@user146780: So what? Just to this again: `std::vector<std::vector<std::vector<double> > > threed(32, values);`
sbi
@user146780: So Jerry Coffin has it right. Just repeat the same pattern one more time to achieve the third dimension.
ereOn
+2  A: 

here you go:

    vector<vector<vector<int> > > k(32, vector<vector<int> >(32, vector<int>(16,0)));

I am not even going to ask why you would want such a monstrosity and not just use a single vector with your own indexing scheme.

shoosh
I type too slowly, definitely. But I did noticed the `double` in his requirements :D
Matthieu M.
Thanks, that's what I was looking for, I'm gonna use this to generate textures in OpenGL ex (1024,768,4)
Milo
OpenGL will expect the row and columns to be in the same address block. You really ought to consider using a single vector and a custom indexing scheme, or a class that looks like a 3d vector but is actually a single vector underneath.
caspin
Using this for an OpenGL texture will not work and will likely crash your program. For a texture you need a single vector with 1024*768*4=3,145,728 elements. A `vector<>` object is just some data members and a pointer to the data it does not contain the actual buffer in itself.
shoosh
+5  A: 

One liner:

std::vector< std::vector< std::vector<double> > > values(32, std::vector< std::vector<double> >(32, std::vector<double>(16, 0.0)));

Or breaking the lines:

typedef std::vector<double> v_type;
typedef std::vector<v_type> vv_type;
typedef std::vector<vv_type> vvv_type;

vvv_type values(32, vv_type(32, v_type(16, 0.0)));

I would remark that this allocate a fair lot of objects (32*32*16).

Would a single vector work ?

std::vector<double> values(32*32*16, 0.0)

That would be 32*32*16-1 less new.

Matthieu M.
I think OpenGL requires a 3d array though?
Milo
OpenGL requires a 1d array, internally segmented.
shoosh
Nested vectors will not work with OpenGL.
Alan
In general, I'd use a `boost::multi_array` for multi-dimensional arrays (one `new`), but I don't think there's any way to use that with OpenGL :(
Brendan Long
A: 

Since the size is known before hand and you will need to convert the whole array to a 1D array (for OpenGL) why not create a class for it? I have created a template-based implementation of a 3D array which I hope will be useful to you.

Usage:

typedef Array3D<double, 3, 3, 3> DoubleArray333;
DoubleArray333 array;
Double val = 0.0;
for (size_t i = 0; i < DoubleArray333::SizeX; ++i)
{
 for (size_t j = 0; j < DoubleArray333::SizeY; ++j)
 {
  for (size_t k = 0; k < DoubleArray333::SizeZ; ++k)
  {
   array(i, j, k) = val++;
  }
 }
}
for (size_t i = 0; i < DoubleArray333::ArraySize; ++i)
{
 std::cout<<array[i]<<" ";
}


The Array3D header file:

#pragma once

#include <exception>
#include <sstream>
#include <utility>
#include <memory>

/**
 * \brief   A 3D array of variable type and size.
 * \author  Vite Falcon
 * \date    08/06/2010
**/
template <typename T, int x, int y, int z>
class Array3D
{
private:
    T* m_array;

    /**
     * \brief   Validate the index range of different dimensions.
     * \remarks Vite Falcon, 08/06/2010.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \exception   std::out_of_range   Thrown when one of the indices is out-of-range.
     * \param   x   The width index.
     * \param   y   The height index.
     * \param   z   The depth index.
    **/
    inline void validateRange(size_t x, size_t y, size_t z)
    {
        if (x >= SizeX || y >= SizeY || z >= SizeZ)
        {
            std::stringstream ss;
            ss<<"Index out of range when accessing ("<<x<<", "<<y<<", "<<z<<
                ") when total size is ("<<SizeX<<", "<<SizeY<<", "<<SizeZ<<").";
            throw std::out_of_range(ss.str());
        }
    }

    /**
     * \brief   Validates the given array index.
     * \remarks Vite Falcon, 08/06/2010.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \exception   std::out_of_range   Thrown when the index is out-of-range.
     * \param   index   Zero-based index of the array.
    **/
    inline void validateIndex(size_t index)
    {
        if (index >= ArraySize)
        {
            std::stringstream ss;
            ss<<"Index out of range when accessing array by index "<<index<<
                " when total array size is "<<ArraySize<<".";
            throw std::out_of_range(ss.str());
        }
    }
public:
    static const size_t SizeX;
    static const size_t SizeY;
    static const size_t SizeZ;
    static const size_t ArraySize;

    typedef Array3D<T,x,y,z> MyType;

    /**
     * \brief   Default constructor. 
     * \author  Vite Falcon
     * \date    08/06/2010
    **/
    Array3D(void)
        :m_array(new T[ArraySize])
    {
    }

    /**
     * \brief   Copy constructor.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   other   The other.
    **/
    Array3D(const MyType& other)
        :m_array(new T[ArraySize])
    {
        memcpy_s(m_array, sizeof(T)*ArraySize, other.m_array, sizeof(T)*ArraySize);
    }

    /**
     * \brief   Destructor.
     * \author  Vite Falcon
     * \date    08/06/2010
    **/
    ~Array3D(void)
    {
        delete[] m_array;
        m_array = 0;
    }

    /**
     * \brief   Gets the value at a particular array index.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   array_index Zero-based index of the array.
     * \return  The value at the given index.
    **/
    inline T& at(size_t array_index)
    {
        return (*this)[array_index];
    }

    /**
     * \brief   Gets the value at a particular array index (const version)
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   array_index Zero-based index of the array.
     * \return  The value at the given index.
    **/
    inline const T& at(size_t array_index) const
    {
        return (*this)[array_index];
    }

    /**
     * \brief   Gets the value in the array from the given 3D indices.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   x   The width index.
     * \param   y   The height index.
     * \param   z   The depth index.
     * \return  The value at the given indices.
    **/
    inline T& at(size_t x, size_t y, size_t z)
    {
        return (*this)(x, y, z);
    }

    /**
    * \brief    Gets the value in the array from the given 3D indices (const version).
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   x   The width index.
     * \param   y   The height index.
     * \param   z   The depth index.
     * \return  The value at the given indices.
    **/
    inline const T& at(size_t x, size_t y, size_t z) const
    {
        return (*this)(x, y, z);
    }

    /**
     * \brief   The '()' operator to access the values as a 3D array.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \return  The value at the given indices.
     *
     * \param   x   The width index.
     * \param   y   The height index.
     * \param   z   The depth index.
    **/
    inline T& operator ()(size_t x, size_t y, size_t z)
    {
        validateRange(x, y, z);
        return m_array[x*SizeY*SizeZ + y*SizeZ + z];
    }

    /**
     * \brief   The '()' operator to access the values as a 3D array (const version).
     * \author  Vite Falcon
     * \date    08/06/2010
     * \return  The value at the given indices.
     *
     * \param   x   The width index.
     * \param   y   The height index.
     * \param   z   The depth index.
    **/
    inline const T& operator()(size_t x, size_t y, size_t z) const
    {
        validateRange(x, y, z);
        return m_array[x*SizeY*SizeZ + y*SizeZ + z];
    }

    /**
     * \brief   The '[]' operator to access the values as a 1D array.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   array_index Zero-based index of the array.
     * \return  Value at the given index.
    **/
    inline T& operator[](size_t array_index)
    {
        validateIndex(array_index);
        return m_array[array_index];
    }

    /**
     * \brief   The '[]' operator to access the values as a 1D array.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   array_index Zero-based index of the array.
     * \return  Value at the given index.
    **/
    inline const T& operator[](size_t array_index) const
    {
        validateIndex(array_index);
        return m_array[array_index];
    }

    /**
     * \brief   Fills the array with the given value.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   val The value to fill the array.
    **/
    void fill(const T& val)
    {
        for (size_t i = 0; i < ArraySize; ++i)
        {
            m_array[i] = val;
        }
    }

    /**
     * \brief   Gets the raw array.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \return  The 1D array.
    **/
    T* getArray()
    {
        return m_array;
    }

    /**
     * \brief   Swaps the current array with the given one.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param [in,out]  other   The other.
    **/
    void swap(MyType& other)
    {
        std::swap(m_array, other.m_array);
    }

    /**
     * \brief   Copy operator.
     * \author  Vite Falcon
     * \date    08/06/2010
     * \param   other   The other.
     * \return  A shallow copy of this object.
    **/
    MyType& operator = (const MyType& other)
    {
        MyType temp(other);
        swap(temp);
        return *this;
    }
};

template <typename T, int x, int y, int z>
const size_t Array3D<T, x, y, z>::SizeX = x;

template <typename T, int x, int y, int z>
const size_t Array3D<T, x, y, z>::SizeY = y;

template <typename T, int x, int y, int z>
const size_t Array3D<T, x, y, z>::SizeZ = z;

template <typename T, int x, int y, int z>
const size_t Array3D<T, x, y, z>::ArraySize = x*y*z;


You can also get the pointer to the array as a 1D by using the function:
double* double_array = array.getArray();

EDIT: Changed the usage to show it with double rather than int.

Vite Falcon