Home > Back-end >  C passing lambdas and vectors to emplace_back for custom class constructor
C passing lambdas and vectors to emplace_back for custom class constructor

Time:12-12

#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
class Monkey
{
public:
  int itemsProcessed{0};
  std::vector<int> heldItems;
  std::function<int(int)> operationFunction;
  std::function<int(int)> testFunction;

  Monkey(std::vector<int> sI, std::function<int(int)> oF, std::function<int(int)> tF)
  {
    heldItems = sI;
    operationFunction = oF;
    testFunction = tF;
  }
  void addItem(int item)
  {
    heldItems.push_back(item);
  }
  std::vector<std::pair<int, int>> processItems()
  {
    std::vector<std::pair<int, int>> redistributedItems;
    for (auto i : heldItems)
    {
      int adjusted = operationFunction(i);
      // Divide by 3 after monkey doesn't break it. Floor is applied by default for int division
      adjusted /= 3;
      int toMonkey = testFunction(adjusted);
      redistributedItems.emplace_back(toMonkey, adjusted);
    }
    return redistributedItems;
  }
};

int main(int argc, char *argv[])
{
  std::vector<Monkey> monkeyList;
  monkeyList.emplace_back(
      {79, 98}, [](int a) -> int
      { return a * 19; },
      [](int a) -> int
      { return a % 23 ? 2 : 3; });
  return EXIT_SUCCESS;
}

In case you're wondering, this is a solution I'm working on for advent of code not any sort of programming assignment.

The issue I'm facing is that I'd like to create a vector of Monkey objects in my main method. It seems to me that I should be able to pass the arguments to the Monkey class constructor (vector, lambda, lambda) to the emplace_back function of the vector class. Whenever I try the above code I get the following error:

error: no matching function for call to 'std::vector<Monkey>::emplace_back(<brace-enclosed initializer list>, main(int, char**)::<lambda(int)>, main(int, char**)::<lambda(int)>)'
   41 |   monkeyList.emplace_back(
      |   ~~~~~~~~~~~~~~~~~~~~~~~^
   42 |       {79, 98}, [](int a) -> int
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~
   43 |       { return a * 19; },
      |       ~~~~~~~~~~~~~~~~~~~
   44 |       [](int a) -> int
      |       ~~~~~~~~~~~~~~~~
   45 |       { return a % 23 ? 2 : 3; });

If I wrap the arguments to emplace_back in braces to use brace initialization, I get the following error:

error: no matching function for call to 'std::vector<Monkey>::emplace_back(<brace-enclosed initializer list>)'
   42 |   monkeyList.emplace_back({{79, 98}, [](int a)
      |   ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
   43 |                            { return a * 19; },
      |                            ~~~~~~~~~~~~~~~~~~~
   44 |                            [](int a)
      |                            ~~~~~~~~~
   45 |                            { return a % 23 ? 2 : 3; }});

What gives? I'd like monkeyList[0] to be an object with heldItems = vector of two ints, 79 and 98, an operationFunction of a lambada that takes an int and returns 19 * that int, and a lambda that returns 2 if the modulo of an int is 23 or 3 otherwise. Relatively new to C so any help is appreciated. Thanks.

CodePudding user response:

The problem is that the emplace_back doesn't know the type of {79, 98} when you're passing it. So you have to specify that it's a std::vector<int>.

  monkeyList.emplace_back(
      std::vector<int>{79, 98}, [](int a) -> int
      { return a * 19; },
      [](int a) -> int
      { return a % 23 ? 2 : 3; });

The reason is because emplace_back is using template parameters, and {79, 98} could be anything, so the compiler doesn't know what it is and it's not allowed to guess.

  • Related