提升::精神::因果报应使用有条件的替代操作符(|)
boost::spirit::karma using the alternatives operator (|) with conditions
我正试图使用boost::spirit::karma
从自己的类Value
生成一个字符串,但我遇到了这个问题。我试着把我的问题提炼成一个简单的例子。
我想从以下类的实例中生成一个具有因果报应的字符串:
class Value
{
public:
enum ValueType
{
BoolType,
NumericType
};
Value(bool b) : type_(BoolType), value_(b) {}
Value(const double d) : type_(NumericType), value_(d) {};
ValueType type() { return type_; }
operator bool() { return boost::get<bool>(value_); }
operator double() { return boost::get<double>(value_); }
private:
ValueType type_;
boost::variant<bool, double> value_;
};
在这里你可以看到我要做的事情:
int main()
{
using karma::bool_;
using karma::double_;
using karma::rule;
using karma::eps;
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
rule<std::back_insert_iterator<std::string>, Value()> value_rule = bool_ | double_;
Value bool_value = Value(true);
Value double_value = Value(5.0);
karma::generate(sink, value_rule, bool_value);
std::cout << generated << "n";
generated.clear();
karma::generate(sink, value_rule, double_value);
std::cout << generated << "n";
return 0;
}
对karma::generate()
的第一个调用运行良好,因为该值是bool,并且我的规则中的第一个生成器也"消耗"了bool。但第二个karma::generate()
与boost::bad_get
一起失败,因为因果报应试图吃掉一个布尔并因此调用Value::operator bool()
。
我的下一个想法是修改我的生成器规则,并将eps()
生成器与一个条件一起使用,但在这里我陷入了困境:
value_rule = (eps( ... ) << bool_) | (eps( ... ) << double_);
我无法用这样的东西填充eps生成器的括号(当然不起作用):
eps(value.type() == BoolType)
我试着进入boost::phoenix
,但我的大脑似乎还没有为这样的事情做好准备。
请帮帮我!
以下是我的完整示例(编译但不工作):main.cpp
想到的最简单的事情是:使用value_
变体(因为Karma非常支持变体)。
在语义动作中使用phoenix绑定将起作用:
rule<std::back_insert_iterator<std::string>, Value()> value_rule;
value_rule = (bool_ | double_)
[ _1 = phx::bind(&Value::value_, _val) ];
尽管这需要公开value_
(例如,给的朋友),所以您可能更喜欢访问器方法。
下面是一个工作示例http://liveworkspace.org/code/22ab2093ad9bd3b03e55a7f3dde952f8
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
class Value
{
public:
enum ValueType
{
BoolType,
NumericType
};
Value(bool b) : type_(BoolType), value_(b) {}
Value(double d) : type_(NumericType), value_(d) {};
ValueType type() { return type_; }
operator bool() { return boost::get<bool>(value_); }
operator double() { return boost::get<double>(value_); }
private:
ValueType type_;
friend int main();
boost::variant<bool, double> value_;
};
namespace karma = boost::spirit::karma;
int main()
{
using namespace karma;
std::string generated;
std::back_insert_iterator<std::string> sink(generated);
rule<std::back_insert_iterator<std::string>, Value()> value_rule;
value_rule = (bool_ | double_)
[ _1 = phx::bind(&Value::value_, _val) ];
Value bool_value = Value(true);
Value double_value = Value(5.0);
karma::generate(sink, value_rule, bool_value);
std::cout << generated << "n";
generated.clear();
karma::generate(sink, value_rule, double_value);
std::cout << generated << "n";
return 0;
}
输出
true
5.0
离题:我可以建议标记转换运算符explicit
(至少),以避免令人讨厌的意外吗?
相关文章:
- 如何使用 soong 命名空间来有条件地编译模块
- 有条件地将默认参数传递给函数(使用"?"运算符)
- 根据模板类型有条件地删除变量
- 有条件地选择带有 decltype() 和三元运算符的类型
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 有条件的打印和计数在 std::map 上有限制
- 如何在 c++ 中有条件地包含标头?
- 如何仅在Qt是用ltcg构建时才有条件地启用ltcg?
- 如何在Visual Studio 2019中有条件地编译c++源文件
- C++可以有条件地向下转换类指针吗
- 使用 SFINAE 有条件地解析分配器成员
- 有条件地删除宏
- 有条件地包含C++标准库
- 如何有条件地将元素添加到 std::array - C++11
- 是否根据编译器版本有条件地包含源文件
- 有条件地启用类C++构造函数
- 我可以有条件地使用多个参数吗?
- 有条件地使用 Boost Python 添加模块
- 提升::精神::因果报应使用有条件的替代操作符(|)
- 有条件地重载操作符