C++17, initialise an array

Viewed 255

I'm (re)learning C++ and want to initialise an array of objects.

struct Pea{
    Pea(double lower, double upper){
        static std::default_random_engine generator;
        static std::uniform_real_distribution<double> distribution(lower,upper);
        weight = distribution(generator);
    }
    double weight;
};

class Items{
    std::array<Pea,10> peas();
public:
    Items(){

    }
    void show(){
        std::for_each(begin(peas),end(peas),
                      [](auto pea){
                          std::cout << pea.weight << std::endl;

                      });
    }
};

The example is a big silly but it's just for learning. I want to initialise the array peas with random weights. But I want to specify the lower and upper limits of random.

The line std::array<Pea,10> peas(1.2,2.3); does not compile, as expected, can anyone suggest a 'modern' way of doing this.

Thanks

2 Answers

Initializing the member in the constructor in case you need to depend on the constructor parameters:

class Items{
    std::array<Pea, 3> peas; // no ()
public:
    Items() : peas({ {0., 1.}, {2., 3.}, {4., 5.} }) {
    }
}

Otherwise, you can initialize it directly:

class Items{
    std::array<Pea, 3> peas{{ {0., 1.}, {2., 3.}, {4., 5.} }};
    // ...
}

Another way:

class Items{
    std::array<Pea, 3> peas = {{ {0., 1.}, {2., 3.}, {4., 5.} }};
    // ...
}

This declares a function called peas that returns a std::array<Pea,10>, and that won't work.

std::array<Pea,10> peas();

Here's my take on what needs to be done:

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

struct Pea{
    Pea(double lower, double upper) {
        // the prng should be seeded - or else it'll start with the same default
        // seed every time. std::random_device is usually good enough, but if you use
        // an old version of MinGW, extra care needs to be taken (see other answers
        // for that):
        static std::default_random_engine generator{std::random_device{}()};

        // don't make the distribution static or else all Peas will share the same
        // distribution:
        std::uniform_real_distribution<double> distribution(lower, upper);

        weight = distribution(generator);
    }
    double weight;
};

class Items{
    std::array<Pea, 4> peas;

public:
    Items() : // use the member initializer list
        peas{{ {0., 1.}, {2., 3.}, {4., 5.}, {6., 7.} }}
    {}

    void show(){
        std::for_each(begin(peas),end(peas),
                      [](auto pea){
                          std::cout << pea.weight << std::endl;
                      });
    }
};

int main() {
    Items i;
    i.show();
}

If you have no other use for the Items constructor, you can initialize peas directly:

class Items{
    std::array<Pea, 4> peas{{ {0., 1.}, {2., 3.}, {4., 5.}, {6., 7.} }};

    // ...
};
Related