Nubcake
Nubcake

Reputation: 469

C++ - Initialiser list for unordered_map of class method function pointers

I'm new to C++11 so I have been experimenting with std::function today and I'm trying to use it to create a hash table for strings to class function pointers for a small assembler I am creating:

assemble.cpp

#include <iostream>
#include <unordered_map>
#include <functional>
#include <vector>
#include <string>

class Assembler {

    public:

    // Assembles the source file and writes it
    bool assemble(std::string output_file);

    // Creates the symbol table from a (.s) file
    bool create_symbol_table(std::string file_name);

    private:

    // Hash table for opcode to functions
    std::unordered_map<std::string,std::function<bool(std::vector<std::string>)>> 
    opcode_map =
    {
     {"add",assemble_data_processing}
    };

    bool assemble_data_processing(std::vector<std::string> instruction);

};

bool Assembler::assemble_data_processing(std::vector<std::string> instruction) {
    std::cout << "Data Processing" << std::endl;    
    return false;
}

This gives me a compile time error with g++:

g++ -Wall -g -Werror -std=c++11 -o assemble.o assemble.cpp

assemble.cpp:28:5: error: could not convert ‘{{"add", ((Assembler*)this)->Assembler::assemble_data_processing}}’ from ‘<brace-enclosed initializer list>’ to ‘std::unordered_map<std::__cxx11::basic_string<char>, std::function<bool(std::vector<std::__cxx11::basic_string<char> >)> >’ }; ^

But if make the function a non-class function then it compiles without problems:

bool assemble_data_processing(std::vector<std::string> instruction) {
    std::cout << "Data Processing" << std::endl;    
    return false;
}

How can I initialise the unordered_map in a brace initialiser list for class methods?

Upvotes: 0

Views: 823

Answers (2)

user4442671
user4442671

Reputation:

A std::function cannot hold non-bound member functions.

You have three ways to fix this depending on the circumstance.

a) If assemble_data_processing does not use any member data, make it a static member function, and call it a day.

b) If your cache is associated with a single Assembler instance, then bind the function using std::bind, using something similar to:

opcode_map =
{
 {"add",std::bind(&Assembler::assemble_data_processing, this, _1)}
};

c) if the Assembler instance is something that gets determined later, then you will have to ditch std::function, and use a good-old function pointer to member function.

Upvotes: 0

declapp auto
declapp auto

Reputation: 678

You can use std::bind

std::unordered_map<std::string,std::function<bool(std::vector<std::string>)>> 
opcode_map =
{
 {"add", std::bind(&Assembler::assemble_data_processing, this, std::placeholders::_1}
};

Or a lambda

std::unordered_map<std::string,std::function<bool(std::vector<std::string>)>> 
opcode_map =
{
 {"add", [this](std::vector<std::string> instruction){return assemble_data_processing(instruction);}}
};

Or make your function static.

Upvotes: 1

Related Questions