提升二进制static_visitor和apply_visitor

whe*_*ies 7 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;
};
Run Code Online (Sandbox Code Playgroud)

但如果我尝试以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);
Run Code Online (Sandbox Code Playgroud)

并从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从图片中取出,就会编译出来.谢谢大家试图帮助我.希望我能给予更多的赞成.

Boa*_*niv 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);
Run Code Online (Sandbox Code Playgroud)

至于二元访问,我认为这不是你想要的.它允许apply_visitor接受两个参数,但两个参数必须是变体.


ild*_*arn 8

@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);
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)