增强精神业力和增强变体“概念”与 汽车发电机相关

发布于 2024-11-01 11:22:18 字数 2835 浏览 0 评论 0 原文

我需要使用其他对象提供的装饰来反序列化 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜中书 2024-11-08 11:22:18

我建议使用 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_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 an operator<<() 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):

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;
        }
    };
}}}

which will map unused_type to karma::eps. This seems to be exactly what you need as eps eats the attribute without generating anything, while succeeding always. If you go this route you will not need to utilize optional<>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文