Search code examples
c++dictionarycastingkey-valuegetter-setter

C++ class with setter that takes an input pointer to later return value to that pointer


I've tried in four different ways to get this to work. I want to assign variables to capture the interface inputs when I call "get_all."


1 - fails because of my lack of understanding of templates

#include <iostream>
#include <string>
#include <map>
using namespace std;
#include <boost/lexical_cast.hpp>

class interface {
    template <typename t> struct val_t{ t val; t& out; };

    map<string, val_t> KeyDict;

    template <typename t> void add(t& out, string key, t value) {
        KeyDict[key] ={ value, out };
    }

    template <typename t> void get_all() {
        for (auto i = KeyDict.begin(); i != KeyDict.end(); ++i) {
            i->second().out = boost::lexical_cast<t>(i.second().val);
        }
    }
};

int main() {
    int i;
    double d;
    string s;
    bool b;

    interface ui;

    ui.add(i, "my int", 1); // if it's not possible do to 1 here, I could do "1";
    ui.add(d, "my double", 3.14);
    ui.add(s, "my string", "good stuff");
    ui.add(b, "my bool", false);

    ui.get_all();

    cout <<
        "int = " << i << endl <<
        "double = " << d << endl <<
        "string = " << s << endl <<
        "bool = " << b << endl;
}

2 - For some reason add() doesn't like string

#include <iostream>
#include <string>
#include <map>
#include <boost/any.hpp>

using namespace std;

class interface {
public:

    struct any { boost::any out; boost::any val; };
    map<string, any> KeyDict;

    template <typename t> void add(t& out, string key, t defval) { KeyDict[key].out = defval; KeyDict[key].val = defval; }

    void get_all() {
        for (auto i = KeyDict.begin(); i != KeyDict.end(); ++i) 
            i->second.out = i->second.val;
    }
};

int main() {
    int i = 0;
    double d = 0;
    string s = "";
    bool b = 0;

    interface ui;

    ui.add(i, "my int", 1); // if it's not possible do to 1 here, I could do "1";
    ui.add(d, "my double", 3.14);
    ui.add(s, "my string", "good stuff");
    ui.add(b, "my bool", false);

    ui.get_all();

    cout <<
        "int = " << i << endl <<
        "double = " << d << endl <<
        "string = " << s << endl <<
        "bool = " << b << endl;

    cin.get();
}

3 - error: attempting to reference a deleted function

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

using namespace std;

class interface {
public:
    struct typer {
        int& i_out;
        double& d_out;
        bool& b_out;
        string& s_out;

        int i = 0;
        double d = 0;
        bool b = 0;
        string s;
        char t = 0;
    };

    map<string, typer> KeyDict_i;
    map<string, typer> KeyDict_d;
    map<string, typer> KeyDict_b;
    map<string, typer> KeyDict_s;

    void add(int& out, string key, int val) { KeyDict_i[key].i_out = out; KeyDict_i[key].i = val; KeyDict_i[key].t = 'i'; }
    void add(double& out, string key, double val) { KeyDict_d[key].d_out = out; KeyDict_d[key].d = val; KeyDict_d[key].t = 'd'; }
    void add(bool& out, string key, bool val) { KeyDict_b[key].b_out = out; KeyDict_b[key].b = val; KeyDict_b[key].t = 'b'; }
    void add(string& out, string key, string val) { KeyDict_s[key].s_out = out; KeyDict_s[key].s = val; KeyDict_s[key].t = 's'; }

    void get_all() {
        for (auto i = KeyDict_i.begin(); i != KeyDict_i.end(); ++i) i->second.i_out = i->second.i;
        for (auto i = KeyDict_d.begin(); i != KeyDict_d.end(); ++i) i->second.d_out = i->second.d;
        for (auto i = KeyDict_b.begin(); i != KeyDict_b.end(); ++i) i->second.b_out = i->second.b;
        for (auto i = KeyDict_s.begin(); i != KeyDict_s.end(); ++i) i->second.s_out = i->second.s;
    }
};

int main() {
    int i = 0;
    double d = 0;
    string s = "";
    bool b = 0;

    interface ui;

    ui.add(i, "my int", 1); // if it's not possible do to 1 here, I could do "1";
    ui.add(d, "my double", 3.14);
    ui.add(s, "my string", "good stuff");
    ui.add(b, "my bool", false);

    ui.get_all();

    cout <<
        "int = " << i << endl <<
        "double = " << d << endl <<
        "string = " << s << endl <<
        "bool = " << b << endl;
}

#3 is the most straightforward because I'm not using any boost or templates. Perhaps that would be the easiest to get working from what I already have?


Solution

  • This works. Thanks for the suggestion, πάνταῥεῖ. This answer is a combination of the 1st and 3rd attempt.

    Run: http://cpp.sh/3j5mp

    #include <iostream>
    #include <string>
    #include <map>   
    
    using namespace std;
    
    class interface {
    public:
        void add(int* out, string key, int val) { ui_i.sub_add(out, key, val); }
        void add(bool* out, string key, bool val) { ui_b.sub_add(out, key, val); }
        void add(double* out, string key, double val) { ui_d.sub_add(out, key, val); }
        void add(string* out, string key, string val) { ui_s.sub_add(out, key, val); }
    
        void get_all() {
            ui_i.sub_get_all();
            ui_b.sub_get_all();
            ui_s.sub_get_all();
            ui_d.sub_get_all();
        }
    private:
        template <typename t> class value_dict {
        public:
            struct key_t { 
                t val;
                t* out; 
            };
    
            map<string, key_t> KeyDict;
    
            void sub_add(t *out, string key, t value) {
                KeyDict[key] ={ value, out };
            }
    
            void sub_get_all() {
                for (auto i = KeyDict.begin(); i != KeyDict.end(); ++i) {
                    *i->second.out = i->second.val;
                }
            }
        };
        value_dict<int> ui_i;
        value_dict<bool> ui_b;
        value_dict<string> ui_s;
        value_dict<double> ui_d;
    };
    
    int main() {
        int i;
        double d;
        string s;
        bool b;
    
        interface ui;
    
        ui.add(&i, "my int", 1); // if it's not possible do to 1 here, I could do "1";
        ui.add(&d, "my double", 3.14);
        ui.add(&s, "my string", "good stuff");
        ui.add(&b, "my bool", false);
    
        ui.get_all();
    
        cout <<
            "int = " << i << endl <<
            "double = " << d << endl <<
            "string = " << s << endl <<
            "bool = " << b << endl;
    
        cin.get();
    }