1

Can anyone explain why I am getting this error?

I am working on an Interface class that gets keyboard input and checks to see whether it is correct through looping through an array of structs which contains strings to compare to and strings to output depending if it is equal to the compare string or not. If the input is correct, it will print the string within the struct and a function within the structure is called and does some action.

interface.hpp

#include <string>
class Input_Interface {
public:
    struct command_output {
    std::string command;
    std::string success_string;
    std::string failure_string;
    void output_function();
    }

    bool stop_loop = false;
    void Clear();
    void Quit_loop();

private:
    std::string input_str;
};

interface.cpp

#include <iostream>
void Input_Interface::Quit_loop() {
   stop_loop = true;
   // ends loop and closes program
}

void Input_Interface::clear() {
   // does some action
}

Input_Interface::command_output clear_output{"CLEAR", "CLEARED", "", Input_Interface::Clear()};
Input_Interface::command_output quit_output{"QUIT", "GOODBYE", "", Input_Interface::Quit_loop()};
Input_Interface::command_output output_arr[]{clear_output, quit_output};

void Input_Interface::begin() {
while (stop_loop == false) {
    Input_Interface::get_input(); //stores input into var called input_str shown later
    this->compare_input();
    }
}

void Input_Interface::compare_input() {
for (unsigned int i=0; i<2; i++) {
    if (this->input_str == output_arr[i].command) {
        std::cout << output_arr[i].success_string << std::endl;
        output_arr[i].output_function();
        break;
        }
    }
    // ... goes through else for failure printing invalid if it did not match any of the command string in the command_output struct array

My issue is with these lines

Input_Interface::command_output clear_output{"CLEAR", "CLEARED", "", Input_Interface::Clear()};
//error: call to non-static function without an object argument

Input_Interface::command_output quit_output{"QUIT", "GOODBYE", "", Input_Interface::Quit_loop()};
//error: call to non-static function without an object argument

I know this is passed through member functions of the class but I don't know how to go about fixing this problem. I'm not really sure if the problem is the scope resolution operator inside the struct object that is causing the error or not because I can use it outside of the struct just fine. Clear() and Quit() cannot be static because it must have access to the the objects in the class.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
GratefulOne
  • 23
  • 1
  • 5
  • 1
    Functions are not objects in C++; you cannot assign functions. Perhaps you are looking for function pointers, or pointers-to-member-function? – Kerrek SB Nov 27 '14 at 16:02
  • Functions are indeed objects in C++, you might be thinking of C. You can assign a template function with std::function. I have already tried using this as std::function rather than declaring Clear() and Quit_loop() as void functions, but I couldn't get it to work either. I'm not sure how a pointer would fix this problem either if I need these functions to work inside my Class. – GratefulOne Nov 27 '14 at 16:05
  • 3
    [`std::is_object`](http://en.cppreference.com/w/cpp/types/is_object) would like to disagree with you. – Kerrek SB Nov 27 '14 at 16:06
  • I suppose you are right. What I stated was Functors (function objects) which are different from functions, you can have functions behave as objects. – GratefulOne Nov 27 '14 at 16:09
  • I'm quite aware of that (and indeed that would come up in an answer). I was just pointing out why your code doesn't work. – Kerrek SB Nov 27 '14 at 16:13
  • Yes it is. Don't worry it will not happen again. – GratefulOne Nov 27 '14 at 16:33

1 Answers1

3

If I'm not mistaken, the output_function in the struct command_output is supposed to store a member function of class Input_Interface.

You'll need to change this:

struct command_output {
    std::string command;
    std::string success_string;
    std::string failure_string;
    void output_function();
}

Into this:

struct command_output {
    std::string command;
    std::string success_string;
    std::string failure_string;
    void (Input_Interface::*output_function)();
}

Then, change the way you initialize the instances from:

Input_Interface::command_output clear_output{"CLEAR", "CLEARED", "", Input_Interface::Clear()};
Input_Interface::command_output quit_output{"QUIT", "GOODBYE", "", Input_Interface::Quit_loop()};

To:

Input_Interface::command_output clear_output{"CLEAR", "CLEARED", "", &Input_Interface::Clear};
Input_Interface::command_output quit_output{"QUIT", "GOODBYE", "", &Input_Interface::Quit_loop};

And finally call them correctly, changing this:

output_arr[i].output_function();

Into this:

(this->*output_arr[i].output_function)();

The error was coming from the fact that you were writing Input_Interface::Clear() or Input_Interface::Quit_loop().

This notation implies two things: the parenthesis indicates that the functions are to be evaluated, and the result passed to the structure initializer, which is not possible since they return void and these functions are called as if they were static member functions, which is not the case.

Chnossos
  • 9,971
  • 4
  • 28
  • 40
  • The last paragraph is missing the point by a lot: The syntax, even if it were valid, would *evaluate a function call*, rather than express the function itself. – Kerrek SB Nov 27 '14 at 16:17
  • I tried to express that with my edit, is this better ? I was having a hard time explaining both problems ... Feel free to edit it if you can make it clearer and more accurate. – Chnossos Nov 27 '14 at 16:23
  • Yeah, it's better, though I imagine the real point of importance is the distinction between "a function" and "the result of calling a function". But I guess it's clear enough. Cheers. – Kerrek SB Nov 27 '14 at 16:25
  • Now I see how Kerrek SB meant by using pointer to function. Thank you both for your help. Thanks for the full explanation Chnossos! – GratefulOne Nov 27 '14 at 16:26
  • yes, it does feel odd to convert it here, but I'm merely following what I think my professor stated. I'll have to double check. I'm trying to write a separate function that converts it, but I'm not sure when to call it. I almost think it would make sense to call it in the overloaded function, so that its the last thing that happens before its written, but I can't get the function call to work in the overloaded function. – JosephTLyons Mar 22 '16 at 07:28