I'm trying to create a map of strings to functions. When it's a simple function, I've seen how to do this like so:
typedef int (*GetIntFunction)(void);
int get_temp()
{
return 42;
}
map<string, GetIntFunction> get_integer_map { { "temp", &get_temp } };
auto iter = get_integer_map.find("temp");
int val = (*iter->second()();
However, I'd like my function pointer to be to a function of a specific object. And, I know which object I need at map creation. Something like this:
class TemperatureModel
{
public:
int GetTemp();
}
TemperatureModel *tempModel = new TemperatureModel();
map<string, GetIntFunction> get_integer_map { { "temp", &(tempModel->GetTemp} };
If you'd like to know why I'm doing this, I'm trying to read a list of parameters from an input file, get their values from the correct model, and then output their values to an output file. I will also need to set values at runtime using a similar map.
The simplest approach to us old-fashioned types is to write a function:
int call_it() {
return tempModel->GetTemp();
}
and store that function in the map in the question:
map<string, GetIntFunction> get_integer_map {
{ "temp", call_it }
};
A newer approach is to use a lambda:
map<string, GetIntFunction> get_integer_map {
{ "temp", [=]() { return tempModel->GetTemp(); }
};
Another approach (as suggested in the comment by Kamil Cuk) is to use std::function to bind the object and the function:
map<string, std::function<int()>> get_integer_map {
{ "temp", std::function<int()>(&TemperatureModel::GetTemp, tempModel) }
};
Caution: code written but not compiled; it may have errors.
Related
I have a few classes and would like to access/update a map in one of the classes.
I am a novice to c++ and am having a hard time to figure out how to achieve this...
Basically, it's adding the work (here it's just a string, but it's actually like I am creating an object using the data from the string (like tokenizing) and need to save that object as a key into the frame map as a value.
paint_service.h
namespace Hello {
namespace World {
class PaintService {
public:
PaintService();
void start_painting(...);
private:
**map<string, string> d_frames;**
}; }}
paint_service.cpp
namespace Hello {
namespace World {
PaintService::PaintService() { }
void PaintService::start_painting(...) {
PaintDistributer paint_distributer;
//works = ... assuming there's this works is like vector of string
for(String work: works) {
paint_distributer.distribute(work);
}
}
}}
paint_distributer.cpp
namespace Hello {
namespace World {
...
Event PaintDistributer::distribute(const string& work) {
string work_type = work.substring(3,5);
if (work_type == "framing") {
**// I wanna add this "work" to the map, d_frames in PaintService, how can I do this?**
return Event(something(work))
}
} }}
Thanks!
A possible solution (untested code).
In PaintService add
void Add(string key, string value) {
d_frames[key] = value;
}
In the call to start_painting add a reference to the owning instance.
PaintDistributer paint_distributer(*this); // constructor needs a reference owner
And in distribute add
if (work_type == "framing") {
owner.Add("distributor", work_type); // or what you want to register.
}
I have a map of callbacks that pass information and execute various functions throughout code, very much like events in C# but in C++.
The map is defined as
std::map<std::string, std::function<void(uint8_t*)>> mCallbacks
It is passed by reference to all subprograms
Then each class binds its callbacks as such
mCallbacks["Status_Label"] = std::bind(&MenuHandler::LabelEditCallback, this, std::placeholders::_1);
Where
bool MenuHandler::LabelEditCallback(uint8_t * m_label_data)
{
int text_size = ((int*)m_label_text)[0];
char* v_text = (char*)&m_label_text[1];
}
And each event gets called from a different subprogram like this:
if (mCallbacks.find("Status_Label") != mCallbacks.end())
mCallbacks.at("Status_Label")((uint8_t*)selected_text);
This makes it easy to pass data and events around the program without making a mess of objects and references
As you can see, this is extremely unsafe, and converting from a uint8_t pointer to various data formats can easily lead to corrupted stack.
The problem is, I don't have a specific structure for callback arguments, some of them may be sending text data, others may be sending numbers.
My solution is to define structs that will be cast to void* when calling the event, and back in the callback function
Something like this (untested):
struct Label_Callback_Data
{
Label_Callback_Data(std::string v_name, std::string v_text)
{
labelName = v_name;
labelText = v_text;
size_of = sizeof(this);
}
int size_of;
std::string labelName;
std::string labelText;
};
And I would call it like this:
if (mCallbacks.find("Status_Label") != mCallbacks.end())
mCallbacks.at("Status_Label")((uint8_t*)Label_Callback_Data("Status_Label_name", "TEXT"))
But then how would I recover it here? If I dont know the exact size of the object?
bool MenuHandler::LabelEditCallback(uint8_t * m_label_data)
{
//?? Label_Callback_Data text_size = (Label_Callback_Data*)m_label_text
}
One solution is to use object with fixed size arrays, but there has to be a C++11 solution that is safe to use, maybe something using dynamic_pointer_casts?
Also, as a bonus question, how would I know if the object passed to the callback function is smaller in size than it is expecting? Is it possible to check this and just return a false from the callback function so the program doesn't crash?
Thank you,
This code is not tested, so there may be logical mistakes I'm willing to correct per responses.
You should generally prefer to use a lambda instead of std::bind().
Try something more like this:
std::map<std::string, std::function<void(void*)>> mCallbacks;
struct Label_Callback_Data
{
std::string labelName;
std::string labelText;
Label_Callback_Data(std::string v_name, std::string v_text)
: labelName(v_name), labelText(v_text) { }
};
...
mCallbacks["Status_Label"] = [this](void *data){ this->LabelEditCallback(data); };
...
auto iter = mCallbacks.find("Status_Label");
if (iter != mCallbacks.end())
{
Label_Callback_Data data("Status_Label_name", "TEXT");
iter->second(&data);
}
...
bool MenuHandler::LabelEditCallback(void *m_label_data)
{
Label_Callback_Data *data = static_cast<Label_Callback_Data*>(m_label_text);
// use data->labelName and data->labelText as needed...
}
Alternatively, you could move the type-cast into the lambda itself, so LabelEditCallback() doesn't need to deal with void* at all:
std::map<std::string, std::function<void(void*)>> mCallbacks;
struct Label_Callback_Data
{
std::string labelName;
std::string labelText;
Label_Callback_Data(std::string v_name, std::string v_text)
: labelName(v_name), labelText(v_text) { }
};
...
mCallbacks["Status_Label"] = [this](void *data){ this->LabelEditCallback(static_cast<Label_Callback_Data*>(data)); };
...
auto iter = mCallbacks.find("Status_Label");
if (iter != mCallbacks.end())
{
Label_Callback_Data data("Status_Label_name", "TEXT");
iter->second(&data);
}
...
bool MenuHandler::LabelEditCallback(Label_Callback_Data *m_label_data)
{
// use m_label_data->labelName and m_label_data->labelText as needed...
}
This is how I did it
...
//The container
std::map<std::string, std::function<void(std::shared_ptr<CallbackData::BlankData>)>> mCallbacks
...
//CALLBACK FUNCTION
bool InputManager::KeyboardCallback(std::shared_ptr<CallbackData::BlankData> callback_data)
{
std::shared_ptr<CallbackData::Keyboard> keyboard_data = std::dynamic_pointer_cast<CallbackData::Keyboard>(callback_data);
if (keyboard_data == nullptr)
return false;
///...
}
...
//CALLBACK EVENT
if (mCallbacks.find("Keyboard") != mCallbacks.end())
{
std::shared_ptr<CallbackData::Keyboard> keyboard_data = std::make_shared<CallbackData::Keyboard>(m_keyboardState);
mCallbacks.at("Keyboard")(std::dynamic_pointer_cast<CallbackData::BlankData>(keyboard_data));
}
...
//Data structure
namespace CallbackData
{
struct BlankData
{
virtual ~BlankData() {};
};
struct Keyboard : public BlankData
{
Keyboard(uint8_t* kb_data)
{
kbData = kb_data;
}
uint8_t* kbData;
};
}
I wrote a special class which checks some states of some external stuff and if something changes I would like to call a callback function.
These function should be not only a global function instead of a function of a special class.
To show what I mean here is some code:
void myClass::addCallbackFunction(unsigned int key, TheSpecialClass* obj, void (TheSpecialClass::*func)(unsigned int, bool)) {
if(!obj) {
return;
}
callbackFunction cbf;
cbf.object = obj;
cbf.func = func;
if(!(callbackFunctions.find(key) == callbackFunctions.end())) {
//Key allready exists.
callbackFunctions[key].push_back(cbf);
} else {
//Key does not exists at the moment. Just create it.
vector<callbackFunction> v;
v.push_back(cbf);
callbackFunctions.insert({key, v});
}
}
void MyClass::callCallbackFunction(unsigned int key, bool newValue) {
vector<callbackFunction> cbfs;
//hasKey..
if(!(callbackFunctions.find(key) == callbackFunctions.end())) {
cbfs = callbackFunctions[key];
}
//calling every function which should be called on a state change.
for(vector<callbackFunction>::iterator it = cbfs.begin(); it != cbfs.end(); ++it) {
((it->object)->*(it->func))(key, newValue);
}
}
//to show the struct and the used map
struct callbackFunction {
TheSpecialClass* object;
void (TheSpecialClass::*func)(unsigned int, bool) ;
};
map<unsigned int, vector<callbackFunction> > callbackFunctions;
Now I want to make 'TheSpecialClass' to some kind of Pointer to a class which can variate. I found void-Pointer but then I have to know which class I passed. I thought there is something like the function pointer out there which I did not found yet.
Do someone know a solution?
I used boost::signal2 to match my usecase.
A tutorial for boost::signal2 is found here.
The signals whould only call functions. Not functions on a special object. There is a workaround by using boost::bind() like:
boost::bind(boost::mem_fn(&SpecialClass::memberFunctionOfTheClass), PointerToTheObjectOfSepcialClass, _1)
The _1 is a placeholder which creates a function (reference) which requires one argument. You can add some more placeholders to use more arguments.
I am still relatively new to C++, learning as I go, and I'm confused as to what is the 'best' way to expose the vector to its consumers. I'm not worried about performance.
I have a class that contains a vector of raw data. I have other classes that need to consume and process that vector.
From reading other posts here I'm not sure whether to return a const reference to the vector or expose const iterators as none of the consumers will modify the vector.
Is one way better than the other? Are there other options or other things to consider ?
typedef std::vector<int> RawNumberContainer;
typedef std::vector<int>::const_iterator RawNumberIterator;
class RawData
{
public:
RawData();
void addNumber(int number)
{
rawNumbers.push_back(number);
}
// this?
RawNumberContainer getRawNumbers() { return rawNumbers; }
// or this?
const RawNumberContainer& getRawNumbersConstReference() { return rawNumbers; }
// or this?
RawNumberIterator getRawNumbersBeginning() { return rawNumbers.begin(); }
RawNumberIterator getRawNumbersEnd() { return rawNumbers.begin(); }
private:
RawNumberContainer rawNumbers;
};
class Something;
class RawDataConsumer
{
public:
// ??
Something* processRawData(RawNumberContainer&);
// ??
Something* processRawData(const RawNumberContainer&);
// ??
Something* processRawData(RawNumberIterator begin, RawNumberIterator end);
};
It:
const RawNumberContainer& getRawNumbersConstReference() const { return rawNumbers; }
And it:
Something* processRawData(const RawNumberContainer&);
You can use:
RawNumberContainer getRawNumbers() const { return rawNumbers; }
This way you'll make sure you can't edit the vector (only read-only access) and spare you of another variable being manually declared in your code.
I'm trying to learn a little more about D's compile time evaluation and understand how its templates, mixins, attributes, etc all work. One thing I'd like to try and do is figure out an elegant way to mark a class's members as being serializable or loadable from a database. In the example below, I've created a tuple that lists which members to use when reading or (later on) serializing the instance.
My first question is, is this a proper usage of tuples as it stands below? And secondly, if so, is there a way to generate this tuple automatically at compile time using the user defined attributes I've assigned to the relevant member variables? I've dug through the various documentation pages like http://dlang.org/attribute.html and http://dlang.org/phobos/std_traits.html but I can't seem to figure out how to use them properly for this purpose (i.e. looping through a class's members and determining which variables have the desired attribute). I'm also not quite certain if I have completely the wrong idea about how attributes are supposed to be used. Any suggestions on the best way to go about this would be appreciated.
enum ENCODABLE = 1;
alias string[string] Row;
template Tuple (T...) { alias T Tuple; }
class A {
#(ENCODABLE) string name;
#(ENCODABLE) int x;
int* p;
alias Tuple!("name","x") encodables;
this(Row row) {
foreach (var; encodables) {
__traits(getMember, this, var) = to!(typeof(__traits(getMember, this, var)))(row[var]);
}
}
}
void main() {
Row row = ["name":"Asdf", "x":"120"]; // Simulated database row
auto a = new A(row);
writefln("%s,%d,%d", a.name, a.x, a.p); // Asdf,120,null
}
This isn't much of an answer, but I used them by defining my own helper templates, and using structs as UDAs (with their values indicating parameters). The helper templates are here:
https://github.com/CyberShadow/ae/blob/master/utils/meta.d#L133
They're used here, to allow overriding the JSON field for a JSON serializer/unserializer:
https://github.com/CyberShadow/ae/blob/master/utils/json.d#L505
I've managed to get it working with the following code, and a little help from the isValueInTuple template based on code provided in CyberShadow's answer. It still feels a bit clunky, but seems to get the job done. Comments/criticism welcome if I'm doing something horrible against the nature of templates!
enum {
ENCODABLE = "ENCODABLE",
};
alias string[string] Row;
template Tuple(T...) { alias T Tuple; }
template isValueInTuple(string s, T...) {
static if (T.length == 0) {
enum bool isValueInTuple = false;
} else static if (T.length == 1) {
static if (is(typeof(T[0]) == typeof(s))) {
enum bool isValueInTuple = T[0] == s;
} else {
enum bool isValueInTuple = false;
}
} else {
enum bool isValueInTuple = isValueInTuple!(s, T[0]) || isValueInTuple!(s, T[1..$]);
}
}
template GenEncodables(U) {
string GenEncodables() {
string ret = "alias Tuple!(";
int fn = 0;
foreach (index, field; __traits(allMembers, U)) {
static if (field != "Monitor") { // better way to avoid compilation errors here?
static if (isAssignable!(typeof(mixin(U.stringof~"."~field)))) {
static if (isValueInTuple!(ENCODABLE, __traits(getAttributes, mixin(U.stringof~"."~field)))) {
if (fn++)
ret ~= ",";
ret ~= `"`~field~`"`;
}
}
}
}
ret ~= ") encodables;";
return ret;
}
}
mixin template Encodables() {
mixin(GenEncodables!(typeof(this)));
}
class A {
#ENCODABLE string name;
#ENCODABLE int x;
int *p;
this() {}
mixin Encodables; // must come after this() definition, apparently!
this(Row row) {
foreach (var; encodables) {
pragma(msg, "Reading parameter "~var~" from row");
__traits(getMember, this, var) = to!(typeof(__traits(getMember, this, var)))(row[var]);
}
}
}