boost::static_visitor как значение карты
Я пытаюсь создать таблицу поиска для ints для boost::static_visitor
using VariableValue = boost::variant<int, double, std::string>;
struct low_priority {};
struct high_priority : low_priority {};
struct Mul : boost::static_visitor < VariableValue>{
template <typename T, typename U>
auto operator() (high_priority, T a, U b) const -> decltype(VariableValue(a * b)) {
return a * b;
}
template <typename T, typename U>
VariableValue operator() (low_priority, T, U) const {
throw std::runtime_error("Incompatible arguments");
}
template <typename T, typename U>
VariableValue operator() (T a, U b) const {
return (*this)(high_priority{}, a, b);
}
};
const std::map < int, boost::static_visitor<VariableValue> > binopHelper = {
{1, Mul{}}
};
Однако когда я делаю следующее:
std::cout << (VariableValue)boost::apply_visitor(binopHelper.at(1), (VariableValue)2, (VariableValue)4) << std::endl;
Я получаю сообщение об ошибке:
термин не оценивает функцию, принимающую 2 аргумента (компиляция исходного файла интерпретатор.cpp)
Как я могу сделать так, чтобы static_visitor принимал 2 аргумента, чтобы соответствовать аргументу Mul
?
1 ответ
Вы будете резать. Вам нужно динамическое размещение. Самый быстрый способ - использовать стирание шрифта.
Хитрость заключается в том, чтобы создать фиксированный статически известный прототип. В этом случае это будет двоичная функция, и вы можете добавитьapply_visitor
отправка в Mul
объект:
#include <boost/variant.hpp>
#include <functional>
#include <iostream>
#include <map>
using VariableValue = boost::variant<int, double>;
struct Mul : boost::static_visitor<VariableValue> {
struct high_priority{};
struct low_priority{};
auto operator() (VariableValue const& a, VariableValue const& b) const {
return boost::apply_visitor(*this, a, b);
}
template <typename T, typename U>
auto operator() (high_priority, T a, U b) const -> decltype(VariableValue(a * b)) {
return a * b;
}
template <typename T, typename U>
VariableValue operator() (low_priority, T, U) const {
throw std::runtime_error("Incompatible arguments");
}
template <typename T, typename U>
VariableValue operator() (T a, U b) const {
return (*this)(high_priority{}, a, b);
}
};
const std::map < int, std::function<VariableValue(VariableValue const&, VariableValue const&)> > binopHelper = {
{1, Mul{}}
};
int main() {
VariableValue i(42), d(3.1415926);
std::cout << binopHelper.at(1)(i, d) << "\n";
std::cout << binopHelper.at(1)(d, i) << "\n";
}
Печать:
131.947
131.947
ДОПОЛНИТЕЛЬНЫЕ ИДЕИ
Похоже, вы реализуете оценку выражения. Вы можете сделать намного проще, например, повторно используя стандартную библиотеку. У меня здесь довольно обширная демонстрация: https://github.com/sehe/qi-extended-parser-evaluator/blob/master/eval.h Она была разработана на [SO] в ходе обсуждения в чате здесь: https://chat.stackoverflow.com/transcript/210289/2020/3/25
Спросите меня о чем угодно, если хотите узнать больше.
В частности, код там показывает, как обрабатывать несоответствия типов и неявные преобразования типа bool, где это необходимо.