Я разработал механизм выполнения сценариев, который имеет много встроенных функций, таким образом, для вызывания любой функции мой код просто вошел if .. else if .. else if
стена, проверяющая имя, но я хотел бы разработать более эффективное решение.
Я должен использовать hashmap со строками как ключи и указатели как значения? Как я мог сделать это при помощи карты STL?
Править: Другая точка, которая вошла в мой ум: конечно, использование карты вызовет компилятор не к подставляемым функциям, но мой неэффективный подход не имел никаких издержек сгенерированными необходимостью вызовов функции, это просто выполняет код.
Так интересно, будут ли издержки, сгенерированные вызовом функции, немного лучше, чем наличие if..else
цепочка.. иначе я мог минимизировать количество сравнений путем проверки символа во времени выполнения (будет длиннее, но быстрее).
Независимо от ваших функций подписи:
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, а не совсем точно функциональные указатели.
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));
Это может быть карта функций совместимых прототипов, конечно,.
Ну, вы можете использовать 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;
}
Вышеуказанные ответы, кажется, дают полный обзор, это касается только вашего второго вопроса:
. log n) сложность. Получение Hashmap по клавише имеет o (1) сложность + немного на стороне в случае столкновений. Поэтому, если Theres хорошая хеш-функция для ваших функций, используйте его. Ваша реализация будет иметь стандартную. Это должно быть хорошо.
Но будьте в курсе, что что-то ниже сотни элементов не принесет пользу всему.
Единственным недостатком хэш-карты является столкновение. В вашем случае Hashmap будет относительно статичным. Вы знаете, что имена функций, которые вы поддерживаете. Поэтому я советую вам создать простой тестовый корпус, где вы называете Unnordered_map <...> :: hash_function со всеми вашими ключами, чтобы убедиться, что ничего не сталкивается. После этого вы можете забыть об этом.
Быстрый Google для потенциальных улучшений на хэш-функциях получил меня туда:
, возможно, в зависимости от ваших соглашений о именах, вы можете улучшить некоторые аспекты функции.