【问题标题】:Boost binary static_visitor and apply_visitor提升二进制 static_visitor 和 apply_visitor
【发布时间】:2011-08-20 11:19:25
【问题描述】:

我有以下代码:

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&amp;, const boost::variant&lt;boost::tuples::tuple&lt;double, double, double, double, double, bool, bool, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type&gt;, boost::tuples::tuple&lt;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&gt;, 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_&gt;&amp;, SearchRescue::Visibility)

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

更新

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

【问题讨论】:

    标签: c++ templates boost


    【解决方案1】:

    @Boaz Yaniv 的回答是 100% 正确的。 boost::apply_visitor&lt;&gt; 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);
    }
    

    如果这种方法仍然对您不起作用,那么您需要编辑您的问题并使用您当前的实际代码更新它。

    附:您使Visibility 成为单一类型boost::variant&lt;&gt; 的方法也应该有效,尽管在我看来这很愚蠢。作为参考,编译如下:

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

    【讨论】:

    • 你是对的。这是我的方法。访问者是一个 const 变量,最终,这就是导致问题的原因。我给了你答案,因为你提供了一个编译的代码版本,迫使我将你的代码与我的代码区分开来。谢谢。
    【解决方案2】:

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

    【讨论】:

    • 这是不正确的。您需要查看有关二进制访问的文档:boost.org/doc/libs/1_46_1/doc/html/variant/…
    • 阅读我的编辑 - 二进制访问仅用于访问相同类型的两个变体,或不同类型的两个变体。它对于访问变体和非变体没有用处,并且仅仅为此而将可见性作为变体的一部分也不是一个好主意。
    • 仍然得到同样的错误。看我上面写的。不过,感谢您的帮助。
    • 确实很奇怪......你不可能忘记包含“ 标题,对吧?像我上面描述的代码肯定适用于我,虽然不在 GCC 上。
    • 顺便说一句,你说过你得到了 same 错误吗?你不应该用我的代码得到相同的。如果你不使用 Visibility 参数调用 boost::apply_visitor,最后一部分 (SearchRescue::Visibility) 肯定不会出现。
    猜你喜欢
    • 2020-12-20
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2019-08-25
    • 2010-09-14
    • 2021-07-11
    相关资源
    最近更新 更多