4

我需要std::vector<boost::variant<..>>用其他对象提供的装饰反序列化 a 。

“装饰”启用的一件事是向量中的一个空条目。我在实际实施中遇到了障碍。但是,我设法将其收缩包装。编译的代码:

#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错误......

error: no type named 'properties' in 'boost::spirit::karma::no_auto_mapping_exists'

现在我必须弄清楚如何将 undefined 映射为无操作以获得干净的转换。这个精神文档条目(特别是这个)描述了我需要研究的内容。是否存在由 Spirit 提供的通用未定义类型或在 boost 中定义的类型,该 Spirit 已经映射为 no-op ?

编辑2:

std::vector<boost::optional<boost::variant<..>>>开始看起来很有吸引力,因为精神为他们提供了类型推断。

4

1 回答 1

3

我建议将其spirit::unused_type用于此目的,因为 Spirit 已经“知道”它并且它具有operator<<()预定义(但任何其他类型都可以) - 并不是说​​您首先真的需要 Karma 的运算符。

此外,您必须提供专业化create_generator(正如您所怀疑的那样):

namespace boost { namespace spirit { namespace traits
{
    template <>
    struct create_generator<spirit::unused_type>
    {
        typedef spirit::karma::eps_type type;

        static type call()
        {
            return spirit::karma::eps;
        }
    };
}}}

这将映射unused_typekarma::eps. 这似乎正是您所需要的,因为eps在不产生任何东西的情况下吃掉了这个属性,同时总是成功。如果您走这条路线,您将不需要使用optional<>.

于 2011-04-14T17:07:22.107 回答