我已将问题浓缩到下面的(可能不是最小的)示例应用程序。该示例是一个通用的JSON解析器。 但是,它表现出两个问题。 1.当没有其他选项通过时,当bool_是变量列表中的输出器时,它总是输出true或false。如果不是最后一个,那么它之后的任何内容都会被有效地使用。我无法弄清楚为什么。 2.当输入是字符串时,字符串处理程序永远不会从变量中触发。当在变体之外使用时,它会发射。
示例代码将字符串输出简化为karma :: string,但仍然显示错误。当我学习这里学到的东西并返回真正的应用程序时,字符串输出将是一个C风格的转义字符串,所以只适用于karma :: string的东西无济于事。
我已经阅读(并重新阅读)Output of a boost::variant type using boost::spirit::karma和boost::spirit::karma output of string in quotation marks并且要么无法正确应用于我的案例(即我毕竟不理解答案)否则它不会'在更复杂的例子中工作。我也熟悉mini_xml示例代码。
对我做错的任何建议?为什么我在做什么是错的,修复是对的?
非常感谢所有帮助。
#include <boost/variant/recursive_variant.hpp>
#include <string>
#include <vector>
namespace lloyd
{
namespace json
{
struct null
{
bool operator==(const null& cmp) {return true; }
};
struct element;
typedef boost::make_recursive_variant<null, bool, long, double, std::string, std::vector<element>, std::vector<boost::recursive_variant_> >::type value;
struct element
{
std::string name;
json::value value;
inline element(const element& src): name(src.name), value(src.value) {}
inline element(const std::string& name, const json::value& value): name(name), value(value) {}
inline element() {}
};
typedef std::vector<element> object;
}
}
#include <boost/fusion/adapted.hpp>
BOOST_FUSION_ADAPT_STRUCT(
lloyd::json::element,
(std::string, name)
(lloyd::json::value, value)
)
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/karma_auto.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace lloyd { namespace json { namespace karma {
template <typename OutputIterator>
struct json_object_out_generator
: boost::spirit::karma::grammar<OutputIterator, json::object(bool, unsigned, unsigned) >
{
// JSON Output Grammars
boost::spirit::karma::rule<OutputIterator, std::vector<json::value>(bool, unsigned, unsigned) > array_rule;
boost::spirit::karma::rule<OutputIterator, json::null(bool, unsigned, unsigned) > null_rule;
boost::spirit::karma::rule<OutputIterator, json::value(bool, unsigned, unsigned) > value_rule;
boost::spirit::karma::rule<OutputIterator, json::element(bool, unsigned, unsigned) > elem_rule;
boost::spirit::karma::rule<OutputIterator, json::object(bool, unsigned, unsigned) > obj_rule;
json_object_out_generator() : json_object_out_generator::base_type(obj_rule)
{
using boost::spirit::lit;
using boost::spirit::_r1;
using boost::spirit::_r2;
using boost::spirit::_r3;
namespace karma=boost::spirit::karma;
null_rule %= karma::eps << boost::spirit::karma::lit("null");
array_rule %= lit("[") << -(value_rule(_r1, _r2, _r3) % lit(",") ) << "]";
value_rule %= ( null_rule(_r1, _r2, _r3) | karma::string | karma::long_ | karma::double_ | obj_rule(_r1, _r2, _r3) | array_rule(_r1, _r2, _r3) | karma::bool_);
elem_rule %= boost::spirit::karma::string << ":" << -value_rule(_r1, _r2+1, _r3);
obj_rule %= boost::spirit::lit("{")
<< -boost::spirit::buffer[( elem_rule(_r1, _r2+1, _r3) % ',' ) ]
<< "}";
}
};
}}}
#include <vector>
#include <sstream>
#include <iomanip>
#include <boost/assign/list_of.hpp>
#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
int main(int argc, const char* argv[])
{
using lloyd::json::value;
using lloyd::json::element;
using lloyd::json::null;
lloyd::json::object obj;
lloyd::json::object sobj;
std::vector<value> t5;
t5 += null(), true, false, value("Testing"), sobj;
obj += element("T1", null()), element("T2", true), element("T3", false);
obj += element("T4", "Testing 4"), element("T5", t5), element("T6", sobj);
obj += element("NT0", (long)50), element("NT1", 50.5), element("NT2", 50.0);
std::stringstream s;
typedef boost::spirit::karma::ostream_iterator<char> out_itr;
out_itr so(s);
lloyd::json::karma::json_object_out_generator<out_itr> json_object_out; // Our grammar definition
boost::spirit::karma::generate(so, json_object_out(true, 0, 1), obj);
std::cout << "Result:\n";
std::cout << s.str() << std::endl;
return 0;
}
修改标题以涵盖显示的实际问题。 编辑修复代码示例中的上传未命中。
答案 0 :(得分:1)
正如某人的评论所述,缺少的是我错过删除引用(它们存在于此处)的标题,但我删除了使用。
但是,上面的实际问题是C ++基本对象转换规则。万一soemone遇到这个:
c提供从指针类型到布尔值的直接转换。 c ++添加了一个std :: string类。该类提供了const char *。
的构造函数直接转换比类构造函数更简单,因此当可以使用任何一种转换时,首选转换。因为它更简单,所以对于使用哪种转换也不会有歧义。因此,虽然char * to string是预期的,但编译器指向boolean,导致输出为布尔值。
VeXocide在freenode ## spirit聊天频道上提供了这些信息。
所以,为了强制进行所需的转换,如果使用std :: string(“STRING HERE”)而不是“STRING HERE”,它就会起作用。 boost :: spirit :: karma与实际问题无关,因为它是一个gigo问题。