提升二进制static_visitor和apply_visitor

时间:2011-05-06 20:24:14

标签: c++ templates boost

我有以下代码:

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,它会读取上面的所有垃圾以及我为变体选择的任何名称。我已经阅读了binary visitation关于提升的文档,但我很茫然。请注意,所有这些都在同一名称空间内。

更新

我的尝试就是问题所在。上面没有显示我将访问者作为const变量。一旦我从图片中取出const,它就会被编译。谢谢大家试图帮助我。希望我能给予更多的赞成。

2 个答案:

答案 0 :(得分:8)

boost :: apply_visitor只接受一个带有一个参数的访问者,所以它不会接受你的访问者。您可以通过一些绑定来修复它,但我认为一个更好的解决方案就是在您的DetectionGenerator类构造函数中添加Visibility参数:

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接受两个参数,但两个参数必须是变体。

答案 1 :(得分:8)

@Boaz Yaniv的回答是100%正确的。直接boost::apply_visitor<> docs州:

  

接受两个操作数的重载调用给定访问者的二元函数调用操作符对给定变体操作数的内容。

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);
}

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

P.S。您使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);
}