使用额外参数增加变体访问者

时间:2015-04-14 03:25:55

标签: c++ c++11 boost c++14 boost-variant

我的代码类似于下面的代码。

typedef uint32_t IntType;
typedef IntType IntValue;
typedef boost::variant<IntValue, std::string>  MsgValue;

MsgValue v;

而不是这样说,

IntValue value = boost::apply_visitor(d_string_int_visitor(), v);

我想传递一个额外的参数,如下所示:但是operator()给出了编译错误。

//This gives an error since the overload below doesn't work.
IntValue value = boost::apply_visitor(d_string_int_visitor(), v, anotherStr);

class d_string_int_visitor : public boost::static_visitor<IntType>
{
public:
    inline IntType operator()(IntType i) const
    {
        return i;
    }

    inline IntValue operator()(const std::string& str) const noexcept
    {
        // code in here
    }

    //I want this, but compiler error.
    inline IntValue operator()(const std::string& str, const std::string s) const noexcept
    {
        // code in here
    }
};

2 个答案:

答案 0 :(得分:8)

您可以使用std::bind将额外的string参数绑定到访问者。首先,将std::string参数添加到所有访问者的operator()重载中。

class d_string_int_visitor : public boost::static_visitor<IntType>
{
public:
    inline IntType operator()(IntType i, const std::string& s) const
    {
        return i;
    }

    inline IntValue operator()(const std::string& str, const std::string& s) const noexcept
    {
        // code in here
        return 0;
    }
};

现在创建一个绑定了第二个string参数的访问者。

auto bound_visitor = std::bind(d_string_int_visitor(), std::placeholders::_1, "Hello World!");
boost::apply_visitor(bound_visitor, v);

Live demo

但是,更好的解决方案是将字符串作为访问者的构造函数参数传递。

答案 1 :(得分:3)

typedef uint32_t IntType;
typedef IntType IntValue;
typedef boost::variant<IntValue, std::string>  MsgValue;

MsgValue v;

IntValue value = boost::apply_visitor([&](auto&& one){
  return d_string_int_visitor{}(decltype(one)(one), anotherStr);
}, v);

假设d_string_int_visitor的每个重载都可以处理额外的参数。

作为奖励,如果您愿意,甚至可以取消包装课程:

IntValue to_int_value(IntValue v, std::string const& format) { return v; }
IntValue to_int_value(std::string const& str, std::string const& format);

IntValue value = boost::apply_visitor([&](auto&& one){
  return to_int_value(decltype(one)(one), anotherStr);
}, v);

我们创建一个匿名lambda,它转发到一组传统的函数重载。

auto&& onedecltype(one)(one)是一种从lambda(C ++ 14)完美转发的技术。您可以用std::forward<decltype(one)>(one)替换第二个,但我发现短版本可读。与std::forward不同,它会导致错误&#34;具有值类型的东西,但我们知道one是l或r值引用。