0

I could use a define macro to do what I want to achieve. But I'm sure there is a better way with C++14.

Basically I would like to instantiate a std::array of objets in the header of a class without defining by hand each instance.

    const std::array<property<uint16_t>, 16> cmd_eng1 =
    {{
            {PROG_MEM_ENG1, 0},
            {PROG_MEM_ENG1+2, 0},
            ...
            {PROG_MEM_ENG1+30, 0}
    }};

and if you wonder, below is the property class constructor (template not shown).

property(uint8_t addr, uint8_t bit_offset)

So is there a way (other than a macro) to define this array without writing everything by hand?

0

2 Answers 2

1

@Micheal's answered can be slightly improved by using a lambda instead of a function.

This is somewhat similar to the trick used to initialize a local const variable using complex logic without having to write a helper method.

const auto cmd_eng1 = []{
    std::array<property<std::uint16_t>, 16> result = {};

    for (std::size_t i = 0; i < 16; ++i) {
        result[i] = property<std::uint16_t>(PROG_MEM_ENG1 + 2 * i, 0);
    }

    return result;
}();

Edit: This assumes that property can be default-constructed.

If you cannot go through the create-then-assign sequence and have to initialize the array on construction, you have to be a little more crafty and use a variadic template, in which case, I don't think you can avoid having to write a helper function:

template<std::size_t... Is>
auto make_array(std::index_sequence<Is...>) {
   return std::array<property<std::uint16_t>, sizeof...(Is)> {property<std::uint16_t>{PROG_MEM_ENG1 + 2 * Is, 0}...};
}

const auto cmd_eng1 = make_array(std::make_index_sequence<16>());
Sign up to request clarification or add additional context in comments.

6 Comments

I think constexpr lambda are C++17 feature
@Frank, thanks, this seems quite good. However, I'm getting error: could not convert '<brace-enclosed initializer list>()' from '<brace-enclosed initializer list>' to 'driver_LP5562::property<short unsigned int>' I don't understand the problem, yet.
@Victor That's probably because property has no default constructor. See my ammended answer for an alternative in that case.
@Frank, indeed changing the constructor to property(uint8_t addr=0, uint8_t bit_offset=0) works like a charm :)
@Victor You do you in your code base, but adding a default constructor by using default values is pretty bad and error-prone. I would just add a separate default constructor instead. What if someone wrote property(12)?
|
1

Is this a solution to your problem?

template<std::size_t Size>
constexpr std::array<property<std::uint16_t>, Size> makeArray()
{
    std::array<property<std::uint16_t>, Size> array = {};
    for (std::size_t i = 0; i < Size; ++i) {
        array[i] = property<std::uint16_t>(PROG_MEM_ENG1 + 2*i, 0);
    }

    return array;
}

const auto cmd_eng1 = makeArray<16>();

1 Comment

Yes it is, thanks! However I think Frank answer is more readable (for example for another programmer reading the code), but as you pointed out, I'm not sure yet his solution can work with C++14

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.