提升二进制static_visitor和apply_visitor

Boost binary static_visitor and apply_visitor

本文关键字:visitor apply static 二进制      更新时间:2023-10-16

我有以下代码:

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从图片中取出,它就编译了。 谢谢大家试图帮助我。 希望我能给更多的赞成票。

@Boaz Yaniv的答案是100%正确的。boost::apply_visitor<>文档直接指出:

接受两个操作数的重载在给定变体操作数的内容上调用给定访问者的二进制函数调用运算符。

Yaniv 建议的补救措施——在访问者的构造函数中获取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);
}

如果此方法仍然不适合您,那么您需要编辑您的问题并使用实际的当前代码对其进行更新。

附言你把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);
}

boost::apply_visitor 只接受一个接受单个参数的访问者,所以它不会接受你的访问者。您可以使用一些绑定来修复它,但我认为更好的解决方案是在 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接受两个参数,但两个参数都必须是变体。