Boost 二进制 static_visitor 和 apply_visitor

发布于 2024-11-05 21:12:09 字数 2388 浏览 0 评论 0 原文

我有以下代码:

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, boost::detail::variant::void_, boost::细节::变体::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)

如果我尝试包装 < boost::variant 中的 code>Visibility 枚举我只得到相同的错误,而不是 Visibility 它读取上面的所有垃圾以及我为该名称选择的任何名称变体。我已经阅读了有关 boost 的文档 二进制访问,但我不知所措。请注意,所有这些东西都在同一个命名空间内。

更新

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

I have the following code:

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

but if I try to use it with boost::apply_visitor in the following manner:

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

and get the following from gcc:

error: no matching function for call to ‘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)

If I attempt to wrap the Visibility enum within a boost::variant I get the same error only instead of Visibility it reads all that junk above and whatever name I chose for the variant. I've read over the docs on boost for binary visitation but I'm at a loss. Due note, all these things are within the same namespace.

Update:

It was my attempt that was the problem. Not shown above was that I had the visitor as a const variable. Once I took the const out of the picture, it compiled. Thank you all for trying to help me out. Wish I could give more upvotes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晚风撩人 2024-11-12 21:12:09

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

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

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

@Boaz Yaniv's answer is 100% correct. The boost::apply_visitor<> docs state directly:

Overloads accepting two operands invoke the binary function call operator of the given visitor on the content of the given variant operands.

Yaniv's suggested approach for remedying that – taking a Visibility object in the visitor's constructor – is also the proper fix. You indicated that such an approach did not work for you; I'll warrant that the problem was in your attempt and not in the approach. ;-] Here's code that compiles:

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

If this approach continues to fail to work for you then you'll need to edit your question and update it with your actual, current code.

P.S. Your approach of making Visibility a single-type boost::variant<> should work also, though it seems silly to me. For reference, this compiles:

#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);
}
爱本泡沫多脆弱 2024-11-12 21:12:09

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

boost::apply_visitor only takes a visitor that takes a single argument, so it won't accept your visitor. You may be able to fix it with some binding, but I think a nicer solution would be just to add the Visibility argument at your DetectionGenerator class constructor:

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

And as for binary visitation, I don't think this is what you're looking for. It allows apply_visitor to take two arguments, but both arguments must be variants.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文