-3

I am currently implementing a text-file based testing UI that will take mocked up user inputs from a text file (line-by-line) to simulate real user input instead of using std::cin.

The issue arises when I attempt to pass std::cin into std::ifstream parameter; the issue persists whether it is by reference or by value.

Function:

void ZoinkersEngine::displayMainMenu(User& currentUser, std::ifstream& in) {
//need a function to check the role level of the user here

//DEMO (Mock-up) of Menu
std::string option = "";
do {
    std::cout << std::string(40, '\n');
    std::cout << "Successfully logged in...\n\n\n";
    std::cout << "Main Menu:\n";
    std::cout << "[0] Order Plan\n";
    std::cout << "[1] Generate Plan\n\n";

    std::cout << "Please input number of selected option: ";
    // std::cin >> option;
    in >> option;

    if (option == "0") {
        currentUser.calculateExhibitFav(zoinkersDirectory);
        currentUser.orderPlan(zoinkersDirectory);
    }
    else if (option == "1") {
        currentUser.calculateExhibitFav(zoinkersDirectory);
        currentUser.generatePlan(zoinkersDirectory);
    }
    else if (option == "cancel" || option == "Cancel") {
        break;
    }
} while (option != "cancel" || option != "Cancel");}

Call To Function:

engine.displayMainMenu(currentUser, std::cin);

Error:

cannot convert argument 2 from 'std::istream' to 'std::ifstream'

I can not figure this out; as far as I know ifstream is derived from the istream base class, thus the compiler should be able to cast it.

EDIT #1: Current IDE is Visual Studios 2017; answers must also compile on g++ and work on linux.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Jared F.
  • 1
  • 1
  • 3
    Such a conversion is not possible. Make the parameter in the function definition be an istream reference. –  Apr 16 '18 at 21:16
  • You cannot pass `std::cin` "into" a `std::ifstream` parameter because `std::cin` is not a `std::ifstream`. Furthermore, even if it was, you would not be able to pass it by value anyway, as you're doing. You won't be able to pass any real `std::ifstream` into your function, not just `std::cin`. – Sam Varshavchik Apr 16 '18 at 21:16
  • "ifstream is derived from the istream base class". Another way to say that is, "ifstream 'is-a' istream". No cast implied. No cast required. – 2785528 Apr 16 '18 at 21:23
  • @SamVarshavchik because that is not possible is there a way to implement the same logic without creating separate function calls for the different input sources? – Jared F. Apr 16 '18 at 21:24

1 Answers1

2

There is no implicit down casting. If you want the function to take an input stream then it should have the signature

void ZoinkersEngine::displayMainMenu(User& currentUser, std::istream& in)
                                                             ^      ^
                                                             |      reference here
                                                             istream, not ifstream

And now you can pass to it any stream that is an istream or derived from one.

This is necessary as

  1. you cannot pass a stream by value if it is an lvalue since streams are not copyable
  2. casting from a base class to a derived class can only be done when the base class was originally a derived class. This is also only done with pointers otherwise the derived to base class conversion would slice and you lose the derived class part
user4581301
  • 33,082
  • 7
  • 33
  • 54
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Thank you for reply! This is all clear and makes sense to me. However, I am now at square one and cannot seem to think of a way to implement a selective input stream (from a file and std::cin). Any help at all would be greatly appreciated! – Jared F. Apr 16 '18 at 21:34
  • @JaredF. What do you mean? With the way I have it in my answer you can pass `cin` or your own file stream to the function. – NathanOliver Apr 16 '18 at 21:36
  • Ahhhh, please excuse my ignorance. I didn't realize you could use a file as an input stream with istream. Now that I say it outloud it seems like common sense! Thanks for all the help!!! – Jared F. Apr 16 '18 at 21:39
  • @JaredF. No problem. Glad to help. – NathanOliver Apr 16 '18 at 21:40