0

How will I call the functions?

Lets say I have 3 display functions

void disp1()
{
  std::cout<<"\n Disp1 ";
}

void disp2()
{
  std::cout<<"\n Disp2 ";
}

void disp3()
{
  std::cout<<"\n Disp3 ";
}

I want to create a map of these functions and call them according to the key.

fMap["d1"] 

should run that disp1 function. How will I go about this;

If the function has return type other than void I am able to get the value but what about the statements that I need to print. Like the ones above;

Anubhav Rohatgi
  • 458
  • 1
  • 6
  • 16

4 Answers4

3

You can do this with std::map and std::function:

#include <map>
#include <string>
#include <iostream>
#include <functional>

void disp1()
{
  std::cout<<"\n Disp1 ";
}

void disp2()
{
  std::cout<<"\n Disp2 ";
}

void disp3()
{
  std::cout<<"\n Disp3 ";
}

int main()
{
    // add the functions as an initializer-list
    std::map<std::string, std::function<void()>> fMap
    {
          {"d1", disp1}
        , {"d2", disp2}
        , {"d3", disp3}
    };

    // or add them one at a time
    fMap["d1"] = disp1;
    fMap["d2"] = disp2;
    fMap["d3"] = disp3;

    fMap["d1"](); // call them using ()
    fMap["d2"]();
    fMap["d3"]();
}
Galik
  • 47,303
  • 4
  • 80
  • 117
1

To store the lookup index, you would use std::map. This comprises key-value pairs (mymap[ key ] = value). C++ allows you to store a pointer to a function, here I use the using keyword to create a type name, func_t, of the type of fingerprint our function will have: void (*)(void) (this is how you say "pointer to a function which takes void and returns void).

#include <iostream>
#include <string>
#include <map>

// the functions we intend to map
void disp1()
{
  std::cout<<"Disp1\n";
}

void disp2()
{
  std::cout<<"Disp2\n";
}

void disp3()
{
  std::cout<<"Disp3\n";
}

int main() {
    // create a new type, func_t, which describes a pointer
    // to a void function that takes no parameters (void).
    using func_t = void (*)(void);
    // declare a map from a string key to a func_t value,
    // and initialize it with a mapping of f1->disp1, f2->disp2
    // and f3->disp3
    std::map<std::string, func_t> functionMap = {
        { "f1", disp1 }, { "f2", disp2 }, { "f3", disp3 }
    };

    // declare a string for reading input
    std::string input;

    // loop until there is no more input on std::cin.
    while (std::cin.good()) {
        // prompt
        std::cout << "Which disp (f1, f2, f3)? ";
        // fetch the next line of text from cin, without the \n
        std::getline(std::cin, input);
        // if the input is empty we ran out of input or the user
        // input a blank line. either way, stop.
        if (input.empty())
            break;

        std::cout << "You chose " << input << "\n";

        // look for the key in the map. if the key is not found,
        // it will equal the special iterator functionMap.end()
        auto it = functionMap.find(input);
        // If it's not functionMap.end then we have a valid iterator.
        // it->first is the key, it->second is the function pointer.
        if (it != functionMap.end()) {
            // to use a function pointer, just add the () with any
            // arguments after the variable name.
            // remember, it->second is the function pointer.
            it->second();
        } else {
            std::cout << "Invalid entry.\n";
        }
    }
}

Live demo: http://ideone.com/4Xlow1

kfsone
  • 23,617
  • 2
  • 42
  • 74
  • Can we use boost::bind. – Anubhav Rohatgi Feb 11 '16 at 06:13
  • Does the method stated above : using std::maps, has overheads. Like how good it will be if I need to map say 10 functions using maps as compared to switch or if else. – Anubhav Rohatgi Feb 11 '16 at 06:27
  • 2
    You could probably use `boost::bind`, I haven't used boost. You could also use a `std::function`. Using std::maps has some overhead, but if you have 10 functions it will compare fairly well against an if/else chain, a flat array of {key, value}, and you can't use strings as keys in a switch statement. – kfsone Feb 11 '16 at 06:52
0

The answer to your first question is to use std::function in your map.

    std::map<std::string, std::function<void>> fMap {
        {"d1", disp1},
        {"d2", disp2},
        {"d3", disp3}
    };

Your second question about having a return value I would need to think about.

graham.reeds
  • 16,230
  • 17
  • 74
  • 137
0

Solved with the help of @Galik's comment

   #include <iostream>
#include <functional>
#include <algorithm>
#include <map>



typedef std::function<void()> func_t;
typedef std::map<std::string, func_t> func_t_map;

void disp1()
{
    std::cout<<"\n Display 1 "<<std::endl;
    return;
}


void disp2()
{
    std::cout<<"\n Display 2 "<<std::endl;
    return;
}

void disp3()
{
    std::cout<<"\n Display 3 "<<std::endl;
    return;
}

void disp4()
{
    std::cout<<"\n Display 4 "<<std::endl;
    return;
}



int main()
{
    func_t_map fMap;


    fMap["d1"] = disp1;
    fMap["d2"] = disp2;
    fMap["d3"] = disp3;
    fMap["d4"] = disp4;

    fMap["d2"]();

    return 0;
}
Anubhav Rohatgi
  • 458
  • 1
  • 6
  • 16