0

I'm having a problem in my code, I hacked up this simple example to illustrate it.

I have a Player class that has a public enum PlayerType. I have a Manager class with a createPlayer method that accepts a reference to a player and a player type.

But I can't get it to compile -- note, I can't change the signature of the createPlayer method, each param must be an object reference.

What am I doing wrong?

Player.h

#ifndef PLAYER_H
#define PLAYER_H

using namespace std;

class Player {
  public:
    Player();
    enum PlayerType { FORWARD, DEFENSEMAN, GOALIE };
    void setType(PlayerType);
  private:
    PlayerType type;
};

#endif

Player.cc

#include <iostream>

using namespace std;

#include "Player.h"

Player::Player() {
}

void Player::setType(PlayerType type) {
  this->type = type;
}

Manager.h

#ifndef MANAGER_H
#define MANAGER_H

using namespace std;

#include "Player.h"

class Manager {
  public:
    void createPlayer(Player& player, PlayerType& playerType);
};

#endif

Manager.cc

#include <iostream>

using namespace std;

#include "Player.h"

#include "Manager.h"

void Manager::createPlayer(Player& player, PlayerType& playerType) {
  cout << "inside Manager::createPlayer" << endl;
}

Main.cc

#include <iostream>

using namespace std;

#include "Player.h"
#include "Manager.h"

int main() {

  Manager manager;
  Player player;
  manager.createPlayer(player, Player::FORWARD);

  return 0;
}

When I compile gcc -o a.out *.cc *.h I get this error:

In file included from Main.cc:6:0:
Manager.h:10:39: error: ‘PlayerType’ has not been declared
Main.cc: In function ‘int main()’:
Main.cc:12:47: error: no matching function for call to ‘Manager::createPlayer(Player&, Player::PlayerType)’
Main.cc:12:47: note: candidate is:
Manager.h:10:10: note: void Manager::createPlayer(Player&, int&)
Manager.h:10:10: note:   no known conversion for argument 2 from ‘Player::PlayerType’ to ‘int&’
In file included from Manager.cc:7:0:
Manager.h:10:39: error: ‘PlayerType’ has not been declared
Manager.cc:9:44: error: ‘PlayerType’ has not been declared
Manager.h:10:39: error: ‘PlayerType’ has not been declared

What do I do to make this work?

  • You have the wrong code for manager.cc. – Richard Pennington Mar 06 '14 at 22:57
  • @RichardPennington Thx, the code is fixed now. Any ideas? –  Mar 06 '14 at 22:59
  • The problem is that an enum is a constant, not an object. I assume you have a good reason for not changing the signature? (Homework?) How would you create something that can be passed by reference that has the value of the enum you want? – Richard Pennington Mar 06 '14 at 23:01
  • @RichardPennington Yes, the reason I can't change the signature is because the method is provided by the professor that way. However, this question illustrates one issue I'm having in a much larger assignment -- I'm looking for help on one hurdle, not trying to get someone else to do my homework for me. Thx. –  Mar 06 '14 at 23:05
  • I wasn't trying to be critical. Look at Etienne's answer below for one way to solve it. That's what I meant by creating something that you could pass as a reference. – Richard Pennington Mar 06 '14 at 23:07

3 Answers3

2

to be able to use a reference you need to store the value into a variable.

int main() {

  Manager manager;
  Player player;
  Player::PlayerType t = Player::FORWARD;
  manager.createPlayer(player,t);

  return 0;
}
Etienne
  • 16,249
  • 3
  • 26
  • 31
  • That's it! Quick follow up question, to make it work I had to change the param in createPlayer to `Player::PlayerType&` -- how can I make it work with just `PlayerType&`? –  Mar 06 '14 at 23:09
  • You could move the PlayerType enum declaration outside of Player. – Richard Pennington Mar 06 '14 at 23:14
  • you could move the enum definition out of the Player class – Etienne Mar 06 '14 at 23:14
  • I tried moving the 'enum' line above the 'class Player {', and changed all the Player::PlayerType to just 'PlayerType'. But in Main.cc the line 'PlayerType t = PlayerType::FORWARD' gives the compiler error: "‘PlayerType’ is not a class or namespace" -- any ideas? –  Mar 06 '14 at 23:19
  • 1
    The compiler is right, PlayerType isn't a class or namespace. What if you didn't qualify the name? – Richard Pennington Mar 06 '14 at 23:24
  • @RichardPennington Hi Richard, I'll try that, just FYI I posted this question as a new one here: http://stackoverflow.com/questions/22238391/why-am-i-getting-this-enum-is-not-a-class-or-a-namespace-error –  Mar 06 '14 at 23:30
  • @RichardPennington Hmm ... changing it to `PlayerType t = FORWARD;` seems to work -- please post your answer to the new question and I'm happy to mark it as correct after some testing. –  Mar 06 '14 at 23:32
  • @RobertHume Paranaix got the other question right. Give it to him. ;-) – Richard Pennington Mar 06 '14 at 23:34
1

You need to change

void createPlayer(Player& player, Player::PlayerType& playerType);

to

void createPlayer(Player& player, const Player::PlayerType& playerType);

Passing Player::FORWARD as a parameter creates a temporary PlayerType value that can only be passed as a const reference or by value.

gerrit zijlstra
  • 766
  • 4
  • 8
  • Unfortunately he can't change it. – Richard Pennington Mar 06 '14 at 23:09
  • Thx gerrit. Richard is right, I can't change the signature. Looks like I'm halfway there with Etienne's answer. Anyone know the answer to the followup question I gave to Etienne? –  Mar 06 '14 at 23:10
1

The problem is that in this call

manager.createPlayer(player, Player::FORWARD);

the second argument is a temporary object, You may not bind non const reference with a temporary object.

So you should declare function as

void Manager::createPlayer(Player& player, const Player::PlayerType& playerType)

Though I do not see a great sense to use the reference. I would declare the function simpler

void Manager::createPlayer(Player& player, Player::PlayerType playerType)

withou the reference.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335