как создать контейнер со списком функций?

Рейтинг: 0Ответов: 1Опубликовано: 31.05.2023
#include <iostream>
#include <map>

void printStr(const std::string & str)
{
    std::cout << str << std::endl;
}
void printInt(const int & i)
{
    std::cout << i << std::endl;
}
int main()
{
    std::map<std::string, void(*)(...)> map;
    map["prints"] = &printStr;
    map["printi"] = &printInt;
    map["prints"]("12345");
    map["printi"](1234);
    return 0;
}

этот код не работает, а функции с std::cout для примера. я бы хотел составить список указателей на статические функции, чтобы во время исполнения программы можно было вызвать любую из них с любым количеством параметров из командной строки и таким образом менять значения полей экземпляра какого-то своего класса. как правильно это сделать? и есть ли что-то подобное уже готовое в стандартных или бесплатных библиотеках?

Ответы

▲ 5Принят

Вот вариант. Только с вас — как обязательное условие :) — демонстрация того, как именно вы будете это все использовать...

#include <iostream>
#include <map>

typedef void (*sFunc)(const std::string &);
typedef void (*iFunc)(const int &);

void printStr(const std::string & str)
{
    std::cout << str << std::endl;
}
void printInt(const int & i)
{
    std::cout << i << std::endl;
}
int main()
{
    std::map<std::string, void*> map;
    map["prints"] = (void*)printStr;
    map["printi"] = (void*)printInt;
    (sFunc(map["prints"]))("12345");
    (iFunc(map["printi"]))(1234);
    return 0;
}

Update

Набросал простенькое решение, как бы, возможно, делал я (хотя уже вижу ряд улучшений).

#include <vector>
#include <string>
#include <iostream>
#include <sstream>

using namespace std;

class Func
{
public:
    virtual string name() const = 0;
    virtual void doit(const string&) = 0;
};

vector<Func*> funcs;

class Sum: public Func
{
public:
    string name() const override { return "sum"; }
    void doit(const string& s)
    {
        istringstream is(s);
        int a, b;
        string n;
        is >> n >> a >> b;
        cout << a << " + " << b << " = " << (a+b) << endl;
    }
};

class Str: public Func
{
public:
    string name() const override { return "str"; }
    void doit(const string& s)
    {
        cout << "string = " << s << endl;
    }
};

void handle(const string& s)
{
    for(const auto& f: funcs)
        if (s.starts_with(f->name()))
        {
            f->doit(s);
            break;
        }
}


int main(int argc, char * argv[])
{
    funcs.push_back(new Sum);
    funcs.push_back(new Str);


    handle("sum 5 8");
    handle("str Hello world");

}

Есть абстрактный класс, производные — ваши функции, выполняющие сами разбор строки (им виднее!) и нужные вызовы. Объект вносится в какой-то контейнер, при разборе строки выбирается подходящий и работает. Ошибки не обрабатываю, чисто набросок, как и высосанная из пальца функциональность...

Все, что надо для расширения функциональности (новая функция) — новый класс, 2 функции, объект класса в контейнер. Все.