Увеличить двоичный static_visitor и apply_visitor - PullRequest
7 голосов
/ 07 мая 2011

У меня есть следующий код:

typedef boost::variant<LandSearchParameter, WaterSearchParameter> SearchParameter;

enum Visibility{
    CLEAR,
    CLOUDY,
    FOG,
    SMOKE
};

class DetectionGenerator : public boost::static_visitor<double>{
public:

    DetectionGenerator(const EnvironmentalFactors& factors);

    double operator()(const LandSearchParameter& land, Visibility vis) const;
    double operator()(const WaterSearchParameter& water, Visibility vis) const;

private:

    const EnvironmentalFactors mFactors;
};

но если я попытаюсь использовать его с boost::apply_visitor следующим образом:

SearchParameter param = globeCover.generateSearch(lat, lon, altitude);
Visibility vis = weather.generateVisibility(lat, lon, altitude, bearing);
DetectionGenerator detectGen(envFactors);
double prob = boost::apply_visitor(detectGen, param, vis);

и получите следующее от gcc:

ошибка: нет соответствующей функции для вызова ‘apply_visitor(const SearchRescue::DetectionGenerator&, const boost::variant<boost::tuples::tuple<double, double, double, double, double, bool, bool, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>, boost::tuples::tuple<std::size_t, std::size_t, double, double, double, bool, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&, SearchRescue::Visibility)

Если я пытаюсь обернуть перечисление Visibility в boost::variant, я получаю ту же ошибку только вместо Visibility, она читает все эти ненужные файлы и любое имя, выбранное для варианта. Я перечитал документы по повышению для двоичного посещения , но я в растерянности. Обратите внимание, что все эти вещи находятся в одном пространстве имен.

Обновление

Это было моей попыткой, которая была проблемой. Выше не было показано, что у меня был посетитель как const переменная. Как только я вынул const из картинки, она скомпилировалась. Спасибо всем за попытку помочь мне. Хотел бы я дать больше голосов.

Ответы [ 2 ]

8 голосов
/ 07 мая 2011

@ Ответ Вооза Янива на 100% правильный.boost::apply_visitor<> документы напрямую указывают:

Перегрузки, принимающие два операнда, вызывают оператор вызова двоичной функции данного посетителя для содержимого указанных вариантов операндов .

Предложенный Янив подход для исправления этого - получение объекта Visibility в конструкторе посетителя - также является правильным решением.Вы указали, что такой подход не работает для вас;Я гарантирую, что проблема была в вашей попытке, а не в подходе.; -] Вот код, который компилируется:

#include <boost/variant.hpp>

struct LandSearchParameter { };
struct WaterSearchParameter { };
struct EnvironmentalFactors { };

typedef boost::variant<
    LandSearchParameter,
    WaterSearchParameter
> SearchParameter;

enum Visibility
{
    CLEAR,
    CLOUDY,
    FOG,
    SMOKE
};

struct DetectionGenerator : boost::static_visitor<double>
{
    DetectionGenerator(EnvironmentalFactors const& factors, Visibility vis)
      : mFactors(factors),
        mVis(vis)
    { }

    double operator ()(LandSearchParameter const&) const { return 0.; }
    double operator ()(WaterSearchParameter const&) const { return 0.; }

private:
    EnvironmentalFactors mFactors;
    Visibility mVis;
};

int main()
{
    SearchParameter param = LandSearchParameter();
    EnvironmentalFactors const envFactors;
    DetectionGenerator const detectGen(envFactors, CLOUDY);
    double const prob = boost::apply_visitor(detectGen, param);
}

Если этот подход по-прежнему не работает для вас, вам нужно будет отредактировать свой вопрос и обновить его с вашим действующим, текущим кодом.

PS Ваш подход к созданию Visibility однотипного boost::variant<> также должен работать, хотя мне он кажется глупым.Для справки:

#include <boost/variant.hpp>

struct LandSearchParameter { };
struct WaterSearchParameter { };
struct EnvironmentalFactors { };

typedef boost::variant<
    LandSearchParameter,
    WaterSearchParameter
> SearchParameter;

enum VisibilityT
{
    CLEAR,
    CLOUDY,
    FOG,
    SMOKE
};

typedef boost::variant<VisibilityT> Visibility;

struct DetectionGenerator : boost::static_visitor<double>
{
    explicit DetectionGenerator(EnvironmentalFactors const& factors)
      : mFactors(factors)
    { }

    double operator ()(LandSearchParameter const&, VisibilityT const) const
    { return 0.; }

    double operator ()(WaterSearchParameter const&, VisibilityT const) const
    { return 0.; }

private:
    EnvironmentalFactors mFactors;
};

int main()
{
    SearchParameter param = LandSearchParameter();
    EnvironmentalFactors const envFactors;
    DetectionGenerator const detectGen(envFactors);
    Visibility vis = CLOUDY;
    double const prob = boost::apply_visitor(detectGen, param, vis);
}
8 голосов
/ 07 мая 2011

boost :: apply_visitor принимает только посетителя, который принимает один аргумент, поэтому он не примет вашего посетителя. Возможно, вы сможете исправить это с помощью некоторой привязки, но я думаю, что более удачным решением было бы просто добавить аргумент Visibility в ваш конструктор класса DetectionGenerator:

class DetectionGenerator : public boost::static_visitor<double>{
public:

    DetectionGenerator(const EnvironmentalFactors& factors, Visibility vis);

    double operator()(const LandSearchParameter& land) const;
    double operator()(const WaterSearchParameter& water) const;

private:

    const EnvironmentalFactors mFactors;
    const Visibility mVis;
};

SearchParameter param = globeCover.generateSearch(lat, lon, altitude);
Visibility vis = weather.generateVisibility(lat, lon, altitude, bearing);
DetectionGenerator detectGen(envFactors, vis);
double prob = boost::apply_visitor(detectGen, param);

А что касается бинарного посещения, я не думаю, что это то, что вы ищете. Это позволяет apply_visitor принимать два аргумента, но оба аргумента должны быть вариантами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...