sesodesa
sesodesa

Reputation: 1603

Pushing a string to a private member vector

I have a std::vector<std::string> tileSet_ as a member variable of a class. In the constructor of said class I call the function

void MapWindow::shuffleTiles() const
{
  std::vector<std::pair<std::string, unsigned>> tileAmounts = {
    {"a", 2}, {"b", 4}, {"c", 1}, {"d", 4},
    {"e", 5}, {"f", 2}, {"g", 1}, {"h", 3},
    {"i", 2}, {"j", 3}, {"k", 3}, {"l", 3},
    {"m", 2}, {"n", 3}, {"o", 2}, {"p", 3},
    {"q", 1}, {"r", 3}, {"s", 2}, {"t", 1},
    {"u", 8}, {"v", 9}, {"w", 4}, {"x", 1}
  };

  int tileN = 0;
  for (std::vector<std::pair<std::string, int>>::size_type i = 0;
    i < tileAmounts.size();i++) {
    tileN += tileAmounts.at(i).second;
  }

  // only used once to initialise (seed) engine
  std::random_device rd;
  // random-number engine used (Mersenne-Twister in this case)
  std::mt19937 rng(rd());
  // guaranteed unbiased
  std::uniform_int_distribution<int> uni(0,tileAmounts.size() - 1);

  for (int i = 0; i < tileN; i++) {
    auto random_integer = uni(rng);
    //qDebug() << i << ":" << random_integer;
    std::cout << i
              << ":"
              << tileAmounts.at(random_integer).first
              << ":"
              << tileAmounts.at(random_integer).second
              << std::endl
              << std::endl;

    while (tileAmounts.at(random_integer).second < 1) {
      std::cout << "Reshuffling "
               << tileAmounts.at(random_integer).first
               << ":"
               << tileAmounts.at(random_integer).second
               << std::endl;
      random_integer = uni(rng);
    }

    std::string s = tileAmounts[random_integer].first;
    std::cout << s
              << std::endl;

    tileSet_.push_back(s);
    tileAmounts.at(random_integer).second -= 1;
  }

  for (std::vector<std::string>::size_type i = 0;
    i < tileSet_.size();i++) {
    std::cout << tileSet_.at(i)
              << std::endl;
  }
}

which at the very end attempts to push back a randomly picked string from a pair contained in the vector tileAmounts into the memeber vector. For some reason, this raises the error

no matching member function call to 'push_back'

Why does this happen. I'm taking the vector to be pushed back from a std::pair, but surely that shouldn't be causing any type mismatches? A std::string in a std::pair contained in a std::vector is still a std::string, no?

Upvotes: 1

Views: 272

Answers (2)

Loki Astari
Loki Astari

Reputation: 264551

Took me a while to get it all building (with some guesses).

The problem is that the method is marked const. Thus you are not allowed to call any mutating functions on members (ie you can not call none const member functions or none const member functions on any member variables).

 void MapWindow::shuffleTiles() const
                                ^^^^^
 ...
     tileSet_.push_back(s);  // Attempt to mutate the state of the object.

This is explained in greate detail in the error message generated by the compiler:

t2.cpp:61:14: error: no matching member function for call to 'push_back'
    tileSet_.push_back(s);
    ~~~~~~~~~^~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:712:36: note: candidate function not viable: 'this' argument has type
      'const std::vector<std::string>' (aka 'const vector<basic_string<char, char_traits<char>, allocator<char> > >'), but method is not marked const
    _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
                                   ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:715:36: note: candidate function not viable: 'this' argument has type
      'const std::vector<std::string>' (aka 'const vector<basic_string<char, char_traits<char>, allocator<char> > >'), but method is not marked const
    _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x);

If you go to the end of the line it says: "but method is not marked const"

Deciphering line:

note: candidate function not viable: 'this' argument has type
'const std::vector', but method is not marked const
void push_back(const_reference __x);

note: candidate function not viable: 'this' argument has type
'const std::vector', but method is not marked const
void push_back(value_type&& __x);

Upvotes: 3

sesodesa
sesodesa

Reputation: 1603

I figured out the source of the problem: the vectortileSet_ didn't use to be a member variable, but I made it so out of necessity. I had, however, originally defined the function shuffleTiles as a const function, which of course makes it impossible for it to change the state of the class. Removing the const from the definition fixed the issue.

The error messages in C++ can sure be mystical.

Upvotes: 1

Related Questions