Существует ли более чистый синтаксис для передачи функции-члена в базовый класс? ⇐ C++
-
Anonymous
Существует ли более чистый синтаксис для передачи функции-члена в базовый класс?
Существует ли более понятный синтаксис для передачи функции-члена в базовый класс?
В MRE ниже есть ли более чистый синтаксис, чем тот, который я использую для строк:
parse_array("email_addresses", [this]() { this->parse_email_address(); }); parse_array("phone_numbers", [this]() { this->parse_phone_number(); }); Я хочу, чтобы они «выглядели красиво».
Я бы хотел, чтобы они прочитали что-то вроде этого:
parse_array("email_addresses", parse_email_address); parse_array("phone_numbers", parse_phone_number); Вот работающая программа, демонстрирующая первый вариант, описанный выше.
// main.cpp #include #include класс JSON_Parser { защищено: шаблон< класс F > void parse_array(std::string const& key, F parse_element) { parse_key (ключ); parse_element(); } void parse_key (std::string const& ключ) {} }; класс ContactParser: общедоступный JSON_Parser { публика: недействительный анализ() { parse_array("email_addresses", [this]() { this->parse_email_address(); }); parse_array("phone_numbers", [this]() { this->parse_phone_number(); }); } частный: void parse_email_address() {} void parse_phone_number() {} }; интервал основной() { КонтактПарсер КП; CP.parse(); вернуть 0; } // конец файла: main.cpp При необходимости я могу изменить сигнатуру функции-члена parse_array в базовом классе.
Обратите внимание, что создание parse_element виртуальной функции не будет работать, поскольку производный класс (в этом примере) имеет две разные функции, которые вызываются, когда parse_element< /код> вызывается. Вот почему я хочу передать их как обратные вызовы.
Обратите также внимание, что использование std::function в сигнатуре parse_array ничего не изменит в месте вызова.
Наконец, обратите внимание: я не спрашиваю, как передать функцию-член. Есть много ответов на Stack Overflow, посвященных этой теме. Я спрашиваю, можно ли сделать приведенный выше синтаксис «красивым».
Это не то, что я ищу
Конечно, вы можете получить «красивость», если захотите дать лямбдам имена, но это увеличивает объем работы, которую придется проделать человеку при написании производного класса. Вся идея класса JSON_Parser состоит в том, чтобы упростить задачу написания производного класса, а не добавлять к нему дополнения.
Кроме того, по крайней мере на мой взгляд, код читается лучше, если анонимные замыкания размещены в строке.
void parse() { // Это не то решение, которое я ищу. auto parse_email_address = [this]() { this->parse_email_address(); }; auto parse_phone_number = [this]() { this->parse_phone_number(); }; // Это выглядит «красиво». parse_array("адреса_электронной почты", parse_email_address); parse_array("phone_numbers", parse_phone_number); } Немного контекста Как вы, возможно, догадались, класс JSON_Parser — это легкий инструмент, на котором могут основываться другие анализаторы. Он работает с двумя другими низкоуровневыми классами: JSON_Token и JSON_Lexer.
Полный код функции-члена parse_array выглядит следующим образом:
класс JSON_Parser { // Прочие потребности, а затем... шаблон< класс F > void parse_array(std::string const& key, F parse_element) { parse_key (ключ); parse_symbol(':'); parse_symbol('['); if (next_token_is('{') || next_token_is('"')) parse_element(); в то время как (next_token_is(',')) { скан_токен(); parse_element(); } parse_symbol(']'); } } Итак, parse_array предоставляет производным классам простой способ анализа массива JSON. Однако было бы еще проще, если бы синтаксис вызова был чище...
Существует ли более понятный синтаксис для передачи функции-члена в базовый класс?
В MRE ниже есть ли более чистый синтаксис, чем тот, который я использую для строк:
parse_array("email_addresses", [this]() { this->parse_email_address(); }); parse_array("phone_numbers", [this]() { this->parse_phone_number(); }); Я хочу, чтобы они «выглядели красиво».
Я бы хотел, чтобы они прочитали что-то вроде этого:
parse_array("email_addresses", parse_email_address); parse_array("phone_numbers", parse_phone_number); Вот работающая программа, демонстрирующая первый вариант, описанный выше.
// main.cpp #include #include класс JSON_Parser { защищено: шаблон< класс F > void parse_array(std::string const& key, F parse_element) { parse_key (ключ); parse_element(); } void parse_key (std::string const& ключ) {} }; класс ContactParser: общедоступный JSON_Parser { публика: недействительный анализ() { parse_array("email_addresses", [this]() { this->parse_email_address(); }); parse_array("phone_numbers", [this]() { this->parse_phone_number(); }); } частный: void parse_email_address() {} void parse_phone_number() {} }; интервал основной() { КонтактПарсер КП; CP.parse(); вернуть 0; } // конец файла: main.cpp При необходимости я могу изменить сигнатуру функции-члена parse_array в базовом классе.
Обратите внимание, что создание parse_element виртуальной функции не будет работать, поскольку производный класс (в этом примере) имеет две разные функции, которые вызываются, когда parse_element< /код> вызывается. Вот почему я хочу передать их как обратные вызовы.
Обратите также внимание, что использование std::function в сигнатуре parse_array ничего не изменит в месте вызова.
Наконец, обратите внимание: я не спрашиваю, как передать функцию-член. Есть много ответов на Stack Overflow, посвященных этой теме. Я спрашиваю, можно ли сделать приведенный выше синтаксис «красивым».
Это не то, что я ищу
Конечно, вы можете получить «красивость», если захотите дать лямбдам имена, но это увеличивает объем работы, которую придется проделать человеку при написании производного класса. Вся идея класса JSON_Parser состоит в том, чтобы упростить задачу написания производного класса, а не добавлять к нему дополнения.
Кроме того, по крайней мере на мой взгляд, код читается лучше, если анонимные замыкания размещены в строке.
void parse() { // Это не то решение, которое я ищу. auto parse_email_address = [this]() { this->parse_email_address(); }; auto parse_phone_number = [this]() { this->parse_phone_number(); }; // Это выглядит «красиво». parse_array("адреса_электронной почты", parse_email_address); parse_array("phone_numbers", parse_phone_number); } Немного контекста Как вы, возможно, догадались, класс JSON_Parser — это легкий инструмент, на котором могут основываться другие анализаторы. Он работает с двумя другими низкоуровневыми классами: JSON_Token и JSON_Lexer.
Полный код функции-члена parse_array выглядит следующим образом:
класс JSON_Parser { // Прочие потребности, а затем... шаблон< класс F > void parse_array(std::string const& key, F parse_element) { parse_key (ключ); parse_symbol(':'); parse_symbol('['); if (next_token_is('{') || next_token_is('"')) parse_element(); в то время как (next_token_is(',')) { скан_токен(); parse_element(); } parse_symbol(']'); } } Итак, parse_array предоставляет производным классам простой способ анализа массива JSON. Однако было бы еще проще, если бы синтаксис вызова был чище...
Мобильная версия