Используя карту STL указателей функции

Я разработал механизм выполнения сценариев, который имеет много встроенных функций, таким образом, для вызывания любой функции мой код просто вошел if .. else if .. else if стена, проверяющая имя, но я хотел бы разработать более эффективное решение.

Я должен использовать hashmap со строками как ключи и указатели как значения? Как я мог сделать это при помощи карты STL?

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

Так интересно, будут ли издержки, сгенерированные вызовом функции, немного лучше, чем наличие if..else цепочка.. иначе я мог минимизировать количество сравнений путем проверки символа во времени выполнения (будет длиннее, но быстрее).

38
задан RustyTheBoyRobot 19 September 2011 в 14:46
поделиться

4 ответа

Независимо от ваших функций подписи:

typedef void (*ScriptFunction)(void); // function pointer type
typedef std::unordered_map<std::string, ScriptFunction> script_map;

// ...

void some_function()
{
}

// ...

script_map m;
m.emplace("blah", &some_function);

// ...

void call_script(const std::string& pFunction)
{
    auto iter = m.find(pFunction);
    if (iter == m.end())
    {
        // not found
    }

    (*iter->second)();
}

Обратите внимание, что тип Scriptfunction может быть обобщена в STD :: Функция Итак, вы можете поддерживать любую Callable, а не совсем точно функциональные указатели.

45
ответ дан 27 November 2019 в 03:23
поделиться

l = {0 n 1 n : n ≥ 0} Быть неполноценным языком.

Соответствие скобками в выражении можно считать аналогичной формой I.E.

l = {([ n ) n : n ≥ 0}

-121--2714656-

Вы также можете использовать Boost. Функция и Boost.bind Что даже позволяет вам в некоторой степени, иметь карту гетерогенного Функции:

typedef boost::function<void, void> fun_t;
typedef std::map<std::string, fun_t> funs_t;
funs_t f;

void foo() {}
void goo(std::string& p) {}
void bar(int& p) {}

f["foo"] = foo;
f["goo"] = boost::bind(goo, "I am goo");
f["bar"] = boost::bind(bar, int(17));

Это может быть карта функций совместимых прототипов, конечно,.

16
ответ дан 27 November 2019 в 03:23
поделиться

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

int FuncA()
{
    return 1;
}

float FuncB()
{
    return 2;
}


int main()
{
    // Int map
    map<string,int(*)()> int_map;
    int_map["A"] = FuncA;
    // Call it
    cout<<int_map["A"]()<<endl;

    // Add it to your map
    map<string, void(*)> any_map;
    any_map["A"] = FuncA;
    any_map["B"] = FuncB;

    // Call
    cout<<reinterpret_cast<float(*)()>(any_map["B"])()<<endl;
}
3
ответ дан 27 November 2019 в 03:23
поделиться

Вышеуказанные ответы, кажется, дают полный обзор, это касается только вашего второго вопроса:

. log n) сложность. Получение Hashmap по клавише имеет o (1) сложность + немного на стороне в случае столкновений. Поэтому, если Theres хорошая хеш-функция для ваших функций, используйте его. Ваша реализация будет иметь стандартную. Это должно быть хорошо.

Но будьте в курсе, что что-то ниже сотни элементов не принесет пользу всему.

Единственным недостатком хэш-карты является столкновение. В вашем случае Hashmap будет относительно статичным. Вы знаете, что имена функций, которые вы поддерживаете. Поэтому я советую вам создать простой тестовый корпус, где вы называете Unnordered_map <...> :: hash_function со всеми вашими ключами, чтобы убедиться, что ничего не сталкивается. После этого вы можете забыть об этом.

Быстрый Google для потенциальных улучшений на хэш-функциях получил меня туда:

Функции хороших хэш

, возможно, в зависимости от ваших соглашений о именах, вы можете улучшить некоторые аспекты функции.

7
ответ дан 27 November 2019 в 03:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: