0

I'm packing messages to be send to another device. I'm using C++11. Usually the payload is a single ASCII encoded value, but this one command has a bit more parameters. I'm trying to pack the payload in a single array of chars. I'm looking for a clean solution, and I thought that the following (example) solution should work:

Message foo(Parameters parameters) {
    struct __attribute__((__packed__)) ParameterPayload {
        std::array<char,2> a;
        std::array<char,2> b;
        std::array<char,2> c; 
        std::array<char,4> d;
    }; // Actual struct has way more parameters
    ParameterPayload paramPayload;
    paramPayload.a = bar<2,10>(parameters.a);
    paramPayload.b = bar<2,10>(parameters.b);
    paramPayload.c = bar<2,10>(parameters.c);
    paramPayload.d = bar<4,16>(parameters.d);
    
    // This will not work, but I want something like this to work
    auto payload =  reinterpreted_cast<std::array<char, sizeof(ParameterPayload)>(paramPayload);

    return baz<sizeof(ParameterPayload)>(payload);
}

template<size_t size, int base>
std::array<char, size> bar(int input> {
    // ASCII encoding with a base (2, 10 or 16)
}

template<size_t payloadSize>
Message baz(std::array<char, payloadSize> payload) {
    // Some packing computation
}

This is a rough example, but I think it will get the message across. How do I cast the struct to a single std:array<char, N>? Is it even possible? I'm trying not to do multiple std::copies instead, because that will cost more resources and will worsen readability.

another solution I looked into is using

const char* const payload = reinterpret_cast<const char* const>(&paramPayload);

and going from there... I could do a single copy after that, but I'd like to avoid it.

1

1 Answer 1

1

That casting is pedantically UB (and even we don't have guaranty of exact size of std::array).

I suggest to change to something like:

Message foo(Parameters parameters) {
    std::array<char, 2+2+2+4> payload; // Actual struct has way more parameters
    int offset = 0;
    bar<2, 10>(parameters.a, payload.data() + offset, offset);
    bar<2, 10>(parameters.b, payload.data() + offset, offset);
    bar<2, 10>(parameters.c, payload.data() + offset, offset);
    bar<4, 16>(parameters.d, payload.data() + offset, offset);

    return baz(payload);
}

template<size_t size, int base>
void bar(int input, char* out, int& offset) /* std::span<char, size> out (in C++20) */
{
    offset += size;
    // ASCII encoding with a base (2, 10 or 16)
}

template<size_t payloadSize>
Message baz(std::array<char, payloadSize> payload) {
    // Some packing computation
}
Sign up to request clarification or add additional context in comments.

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.