Reputation: 469
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
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
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