Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use a lambda function inside of a vector's constructor?

Is there a way to initialize all values of some container using a lambda function like one would do using std::for_each? I need a 3-dimensional std::vector of random ints, and it would be nice if I could do this within the constructor without having to do another std::for_each loop.

I have tried unsuccessfully the following:

#include <iostream>     /* std::cout */
#include <vector>       /* std::vector */
#include <algorithm>    /* std::for_each */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */



int main(){

    srand(time(nullptr));

    /* only initializes first element, count[0][0][0] */
    std::vector<std::vector<std::vector<int>>> count{100, 
        std::vector<std::vector<int>>{100, 
            std::vector<int>{100, 
            [](){
              return = rand() % 100; 
            }()
          }
       }
    };

    int temp = 0;

   /* here is how I access all elements using std::for_each and lambdas */
   std::for_each(std::begin(count), std::end(count), 
   [&temp](std::vector<std::vector<int>> i){
        std::for_each(std::begin(i), std::end(i), [&temp](std::vector<int> j){
            std::for_each(std::begin(j), std::end(j), [&temp](int k) {
                if(k > temp){
                    temp = k;
                }
            });
        });
    });

}

Any help or ideas are greatly appreciated!

like image 687
user2052561 Avatar asked Oct 20 '25 21:10

user2052561


2 Answers

The elements of the innermost vectors will all be initialized from the result of invoking your lambda, i.e. rand() % 100. They will all be initialized to the same value, and there is no way to get the lambda invoked every time an element (in your case, an int) needs to be initialized.

If you really, really want that to happen transparently, you could just create a type of your own that behaves exactly like an int, but gets default-initialized the way you want:

struct RandomInitInt
{
    RandomInitInt() { i = rand() % 100; }
    RandomInitInt(int i) : i(i) { }
    operator int () { return i; }
    int i;
};

You would then use it this way:

std::vector<std::vector<std::vector<RandomInitInt>>> count(100,
    std::vector<std::vector<RandomInitInt>>(100,
        std::vector<RandomInitInt>(100)
      )
   );

And replace every occurrence of vector<int> with vector<RandomInitInt>.

But again, consider this only if you're desperate about eliminating that loop. Personally, I think the presence of the loop is clearer about the way the vector is initialized - meaning it communicates your intent better.

like image 96
Andy Prowl Avatar answered Oct 23 '25 11:10

Andy Prowl


Feels like std::generate/std::generate_n is what you are looking for

like image 29
user2185945 Avatar answered Oct 23 '25 12:10

user2185945



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!