1

I have a Visual Studio 2008 C++03 application where I would like to initialize a std::vector based on a two dimensional array.

For example:

#define DATA_SIZE 6

struct Data
{
    UINT a;
    BYTE b;
    BYTE c;
    BYTE d;

    Data()
        : /* initialize all members to 0*/
    {
    };

    explicit Data( const BYTE data[ DATA_SIZE ] )
        : a( data[ 0 ] << 16 | data[ 1 ] << 8 | data[ 2 ] ),
          b( data[ 3 ] ),
          c( data[ 4 ] ),
          d( data[ 5 ] )
    {
    };
};

inline bool operator==( const Data& lhs, const Data& rhs )
{
    return /* true if all members are equal */
};

int main( int argc, char* argv[] )
{
    const BYTE source[][ DATA_SIZE ] = 
    {
        { 0x01, 0xfe, 0xaa, 0x01, 0xcc, 0x13 },
        { 0x02, 0xa1, 0x02, 0xbb, 0x02, 0xdd }
    }

    // how should this be done?
    std::vector< Data > data_list( source[ 0 ], source[ countof( source) - 1 ] );

    ASSERT( data_list[ 0 ] == Data( source[ 0 ] ) );
    ASSERT( data_list[ 1 ] == Data( source[ 1 ] ) );
    return 0;
}

Is there a way to do this without a for loop iterating through each item in the data array and calling push_back?

10
  • @ildjarn - edited to make that clearer. Commented May 21, 2012 at 16:42
  • If you removed the explicit keyword would that not allow the compiler to implicitly convert the BYTE arrays to Data objects? Commented May 21, 2012 at 16:45
  • If you used std::tr1::array<BYTE, N> instead of raw C-arrays, this would be completely trivial. Commented May 21, 2012 at 16:50
  • @Dennis - it would, but that wouldn't help. Commented May 21, 2012 at 16:50
  • 1
    @PaulH: No, absolutely not. It would be far better to have the constructor take a first/last range and assert in the constructor that the size of the range is the correct size, or have it take an array<BYTE, DATA_SIZE>, possibly by const&. The use of DATA_SIZE in the declaration gives a false sense of security, as there is no requirement that the provided pointer point to an array of that size. Commented May 21, 2012 at 16:59

2 Answers 2

3

The least change you could make is:

std::vector< Data > data_list(
  &source[ 0 ],
  &source[ countof( source) ] );
Sign up to request clarification or add additional context in comments.

Comments

1

Here's an approach using Boost.Array:

#include <cstddef>
#include <cassert>
#include <vector>
#include <boost/array.hpp>

typedef unsigned UINT;
typedef unsigned char BYTE;

std::size_t const DATA_SIZE = 6;

struct Data
{
    UINT a;
    BYTE b, c, d;

    Data() : a(), b(), c(), d() { }

    Data(boost::array<BYTE, DATA_SIZE> const& data)
      : a(data[0] << 16 | data[1] << 8 | data[2]),
        b(data[3]),
        c(data[4]),
        d(data[5])
    { }
};

inline bool operator ==(Data const& lhs, Data const& rhs)
{
    return lhs.a == rhs.a
        && lhs.b == rhs.b
        && lhs.c == rhs.c
        && lhs.d == rhs.d;
}

int main()
{
    boost::array<boost::array<BYTE, DATA_SIZE>, 2> const source =
    {{
        {{ 0x01, 0xfe, 0xaa, 0x01, 0xcc, 0x13 }},
        {{ 0x02, 0xa1, 0x02, 0xbb, 0x02, 0xdd }}
    }};

    std::vector<Data> data_list(source.begin(), source.end());

    assert(data_list[0] == Data(source[0]));
    assert(data_list[1] == Data(source[1]));
}

Online demo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.