我需要使用其他对象提供的装饰来反序列化 std::vector>
。
“装饰”实现的功能之一是向量中的空条目。我在实际实施中遇到了障碍。不过,我已经成功地把它收缩了。编译的代码:
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
typedef boost::variant<boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
有问题的更改,它尝试实现“未定义”类型以及所需的概念。
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
struct undefined{};
std::ostream & operator<<(std::ostream & out, undefined const & undefined)
{
return out;
}
typedef boost::variant<undefined,boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
如果我注释掉 karma::generate 步骤,std::cout 是一个有效的表达式(Boost::variant OutputStreamable
)。 Spirit 要求生成器的类型必须是 OutputStreamable
(spirit::karma OutputStreamable
),上面的变体应该是 OutputStreamable
因为我已经创建了 undefined
类型 OutputStreamable
作为无操作。
什么给出? :(
我真的开始质疑当使用具有 > 2 级模板间接的库时,C++ 模板机制是否值得。也许我应该回到直接 c。
编辑 1:
好的,Clang 给了我一个明智的first
错误...
错误:'boost::spirit::karma::no_auto_mapping_exists'中没有名为'properties'的类型
现在我必须弄清楚如何将 undefined 映射为无操作以获得干净的转换 精神文档条目(以及这个 具体来说)描述了我需要研究的内容。是否存在由spirit提供的通用未定义类型或boost中定义的类型,该spirit已经映射为无操作
编辑2:
? std::vector>>
开始看起来相当有吸引力,因为 Spirit 为它们提供了类型推导。
I need to deserialize a std::vector<boost::variant<..>>
with decoration supplied by other objects.
One of the things the "decoration" enables is a empty entry in the vector. I have hit a brick wall in my real implementation. However, I have managed to shrink wrap it. Code that compiles :
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
typedef boost::variant<boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
The offending changes, which attempt to implement a "undefined" type, along with the required concept.
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
namespace karma = boost::spirit::karma;
struct undefined{};
std::ostream & operator<<(std::ostream & out, undefined const & undefined)
{
return out;
}
typedef boost::variant<undefined,boost::int32_t, boost::int64_t> custom_variant;
int main()
{
using karma::generate;
custom_variant v;
std::string temp;
std::back_insert_iterator<std::string> x(temp);
std::cout << v;
karma::generate(x, karma::auto_, v);
}
If I comment out the karma::generate
step, std::cout
is a valid expression (Boost::variant OutputStreamable
). Spirit requires that generators be given types which are OutputStreamable
(spirit::karma OutputStreamable
) and the variant above should be OutputStreamable
since I have made the undefined
typeOutputStreamable
as a no-op.
What gives ? :(
I'm really beginning to question weather the C++ template mechanism is worth it when using libraries with > 2 levels of template indirection. Perhaps I should go back to straight-c.
Edit 1:
Ok, Clang gave me a sensible first
error...
error: no type named 'properties' in 'boost::spirit::karma::no_auto_mapping_exists'
Now I got to figure out how to map undefined as a no-op to get a clean conversion. This spirit documentation entry (and this in specific) describes what I need to look into. Is there a generic undefined type provided by spirit or one defined in boost, that spirit already maps as a no-op ?
Edit 2:
std::vector<boost::optional<boost::variant<..>>>
is beginning to look quite appealing since spirit provides type-deduction for them.
发布评论
评论(1)
我建议使用
spirit::unused_type
来达到此目的,因为 Spirit 已经“知道”它,并且它有一个预定义的operator<<()
(但任何其他类型也可以) - 并不是说您首先真的需要 Karma 的运算符。此外,您必须为
create_generator
提供专门化(正如您所怀疑的):它将把
unused_type
映射到karma::eps
。这似乎正是您所需要的,因为 eps 吃掉该属性而不生成任何内容,同时始终成功。如果您选择这条路线,您将不需要使用可选<>
。I'd suggest to use
spirit::unused_type
for that purpose as it already is 'known' to Spirit and it has anoperator<<()
predefined (but any other type will do) - not that you really need that operator for Karma in the first place.In addition, you have to provide a specialization for
create_generator
(as you suspected):which will map
unused_type
tokarma::eps
. This seems to be exactly what you need aseps
eats the attribute without generating anything, while succeeding always. If you go this route you will not need to utilizeoptional<>
.