boost :: static_visitor в качестве значения карты - PullRequest
2 голосов
/ 02 мая 2020

Я пытаюсь создать таблицу поиска для целых чисел для повышения :: 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;

Я получаю ошибку:

term не оценивает функцию, принимающую 2 аргумента (компилятор исходного файла. cpp)

Как сделать так, чтобы static_visitor получал 2 аргумента для соответствует Mul?

1 Ответ

2 голосов
/ 02 мая 2020

Вы бы нарезали . Вам нужно динамическое распределение c. Самый быстрый способ - использовать стирание типа.

Хитрость заключается в создании фиксированного статически известного прототипа. В этом случае это будет двоичная функция, и вы можете добавить диспетчер apply_visitor к объекту Mul:

Live On Coliru

#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#L360 Это было разработано на [SO] в обсуждении в чате здесь: https://chat.stackoverflow.com/transcript/210289/2020/3/25

Спросите меня, если вы хочу узнать больше.

В частности, там показан код, показывающий, как обрабатывать несоответствия типов и неявные преобразования bool, где это уместно.

...