2016-03-07 4 views
1

Я пытаюсь реализовать очень простой клон redis в C++. Поэтому, когда я получаю запросы, мне нужно их разобрать. Сейчас я делаю это:Множественные сравнения строк

void Query::buildQuery(){ 
     std::string query_type = lower(args[0]); 
     if(query_type == "get"){ //do something } 
     else if(query_type == "set"){ //do something } 
     else if(query_type == "getbit"){ //do something } 
     else if(query_type == "setbit"){ //do something } 
     else if(query_type == "zadd"){ //do something } 
     else if(query_type == "zcard"){ //do something } 
     else if(query_type == "zcount"){ //do something } 
     else if(query_type == "zrange"){ //do something } 
     else if(query_type == "save"){ //do something } 
     else { throw(QueryException("Invalid query type")); } 
} 

Есть ли другой, более короткий способ сделать это? Я не хочу включать какую-либо другую библиотеку, кроме STL.

+0

Этот ответ является способом использования переключателя для замены 'if() else if() ...' [Оценить строку с помощью переключателя на C++ [дубликат]] (http://stackoverflow.com/a/16388594/5852567) –

+0

@DIEGOCARRASCAL На самом деле, нет. Я не искал способ изменить, если еще можно переключиться. Я ищу метод, отличный от этих 2 (если есть), который мог бы как-то сделать это. –

ответ

0

Без if...else if, вы можете сделать это switch заявление. Как:

void Query::buildQuery(){ 
     std::string query_type = lower(args[0]); 
     switch(str2int(query_type)){ 
      case str2int("set"):// do something 
       break; 
      case str2int("getbit"):// do something 
       break; 
      ................ 
      .......... 
      default: 
       throw(QueryException("Invalid query type")); 
     } 
} 

Согласно Serhiy где str2int подобно:

constexpr unsigned int str2int(const char* str, int h = 0) 
{ 
    return !str[h] ? 5381 : (str2int(str, h+1)*33)^str[h]; 
} 
+1

С каких пор C++ поддерживает переключение строк? –

+1

Вы не можете ** использовать 'switch' с ключом' std :: string' – NathanOliver

+0

, который может использоваться только с целыми значениями. Таким образом, вам просто нужно преобразовать ваши значения «case» в integer. Вы можете добиться этого, используя constexpr из C++ 11, поэтому некоторые вызовы функций constexpr можно вычислить во время компиляции. –

3

Если эти do_something s может быть извлечен в отдельные методы, то вы можете создать предварительно инициализировать хэш-карту (unordered_map) из строки указатель на функцию члена и сделать что-то вроде

(this->*queryHandlers[query_type])(); 

Вам нужно будет выбрать между множеством фу nctions и одна большая функция.

+0

Это на самом деле отличная идея! Благодаря! –

0

Если вы работаете на процессоре Intel/AMD и чувствуете себя «храбрым», вы можете взглянуть на these implementations of strcmp, strlen, etc, которые используют инструкции SSE. Это будет быстрее.

Что касается общей структуры, вы можете повернуть «set» & «сделать что-то» в класс, который имеет метод тестирования и метод do-something. Имейте массив из них и перебирайте его, вызывая метод теста, передающий query_type. Метод теста для объекта будет автоматически вызывать метод do-something, если он соответствует строке.

Смежные вопросы