-1

How can I use the Boost preprocessor to statically initialize an array with string and pointer pairs as shown below

#include <string>

struct Node;

struct Port
{
    Port(std::string name_, Node* owner_): name(name_), owner(owner_)
    {
    }

    std::string    name;
    Node*          owner;
};

struct Node
{
    // TODO: replace with Port port[4] = { REPEAT_SEQ(RX, 4) };
    Port port[4] = {{"RX_0", this}, {"RX_1", this}, {"RX_2", this}, {"RX_3", this}};
};

int main()
{
    Node node;
}

The problem is that some nodes have lots of ports and writing these port name and owner pointer pairs is tedious and error prone.

I'd like to automate it with the Boost Preprocessor, for example REPEAT_SEQ(RX, 4)

8
  • "and writing these port name and owner pointer pairs is tedious" - too bad, sometimes That's what you have to do . Commented Feb 20 at 14:11
  • Why you think you need preprocessor for this? When I see you want to just initialize some array which is member variable ins some class, then classic constructor code is a best way to do it. Adding here boost prerpocessor will be an overkill and will add cost of maintenance without gains on perfomance.
    – Marek R
    Commented Feb 20 at 14:29
  • If you can express yourself precisely enough, you might be able to persuade ChatGPT to generate the boilerplate for you. I needed an array of 128 random numbers for an HMAC key and ChatGPT knocked it out of the park
    – catnip
    Commented Feb 20 at 14:45
  • BTW what is the C++ standard you are using?
    – Marek R
    Commented Feb 20 at 15:35
  • C++ has had templates and constexpr for more than decade.
    – Öö Tiib
    Commented Feb 20 at 16:04

1 Answer 1

2

Ok turns out your problem is not so simple. Whole problem is caused that is is not so easy to construct an array of types which are not default construable.

Solution with a use of Boost preprocessor is bad idea.
It is best to use meta programing to address this issue. Here is a tool which helps construct an array:

template <typename F, size_t... Is>
auto help_genarate_array(F&& f, std::index_sequence<Is...>)
{
    return std::array { f(Is)... };
}

template <size_t N, typename F>
auto genarate_array(F&& f)
{
    return help_genarate_array(std::forward<F>(f), std::make_index_sequence<N>());
}

With this tool you can initialize now array like this:

struct Node {
    std::array<Port, 4> port;

    Node()
        : port { genarate_array<4>([this](auto i) { return Port { std::format("RX_{}", i), this }; }) }
    {
    }
};

Live demo.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.