【问题标题】:MPL replace without casting the fusion containerMPL 替换而不铸造熔合容器
【发布时间】:2015-06-06 17:52:12
【问题描述】:

我有这门课

struct MyChildrenNeedsSpace : HaveChildren<MyChildrenNeedsSpace>
{
    typedef childrenListType<string, string, string, string> context;

    const   context children;

    MyChildrenNeedsSpace() : children("this", "sentence", "needs", "spaces")
    {
        std::cout << endl << "The children type is:"  << endl << typeid(children).name() << endl;
    }
};

它使用 CRTP 允许 HaveChildren 类访问其子成员变量。

childrenListType 是一个继承自 boost::fusion::vector 的类。

我想以编程方式使 children 成员变量在每个字符串之间包含一个空格类。

所以如果我输入:

<string,string>

孩子变成:

<string, space,string>

如果我输入:

<string,string,string>

变成了

<string,space,string,space,string>

等等

我正在使用 boost fusion,所以它必须在编译时。

我尝试过这样做:

struct MyChildrenNeedsSpaceWithReplacer : HaveChildren<MyChildrenNeedsSpaceWithReplacer>
{
    typedef childrenListType<string, string, string, string> context;
    typedef boost::mpl::replace< context, string, stringAndSpace >::type replacedContext;

    const   replacedContext children;

    MyChildrenNeedsSpaceWithReplacer() : children( "this" ,"sentence" , "needs" , "spaces")
    {
        std::cout << endl << "The children type is:" << endl <<typeid(children).name() << endl;
    }
};

然后 MPL:replace 将容器的类型从我自己的类(继承自 boost::fusion::vector)更改为 boost::fusion::vector4,这会破坏我的流式重载。

您可能会注意到,我将每个字符串替换为 stringAndSpace,而不是 &lt;string,space&gt;

拥有&lt;string,space&gt; 是最好的——但另一种方式对我来说更容易。

总结一下:

typedef boost::mpl::replace< context, string, stringAndSpace >::type replacedContext;

转换我的容器类型 - 你能帮助制作一个可以在编译时将类型定义为以下类的函数

struct childrenListType : public  boost::fusion::vector<CHILDREN_TYPES...>

在我输入的每个字符串之间使用一个空格的模板参数?

我已将完整来源发布在:http://ideone.com/XxYTOt

他们的编译器 typeinfo 说没有 mpl 替换子类型是:16childrenListTypeIISsSsSsSsEE

并与:N5boost6fusion7vector4I14stringAndSpaceS2_S2_S2_EE

您还可以看到流重载失败,因为它输出括号:

(this  sentence  needs  spaces )

【问题讨论】:

  • 不明白,如果你知道每个元素都必须用空格隔开,那为什么不直接在输出所有内容的地方添加空格?另外我想如果你不能处理不同大小的 元组,你的流媒体功能就会被破坏?
  • 我这里贴的代码只是为了展示我要解决的概念。
  • 这不仅仅是让它输出正确的东西——我开始学习 MPL 并被困在这里,所以我希望有人可能会说“哦,你只需要使用 boost ::XXXXX 代替”或告诉我正确的方向。

标签: c++ boost c++14 boost-mpl boost-fusion


【解决方案1】:

对于 C++14,我看不到这里需要提升 - 或者我可能缺少您的要求之一?以下将在纯 C++14 的类型之间添加空格:

struct space {};
template<typename, typename=void> struct spacer;

template<template<typename...> class T>
struct spacer<T<>> { using type = T<>; };

template<template<typename...> class T,typename T1, typename... Ts>
struct spacer<T<T1,Ts...>>
    : spacer<T<T1,Ts...>, std::make_index_sequence<2*sizeof...(Ts)+1>> {};

template<template<typename...> class T,typename... Ts, std::size_t... Ns>
struct spacer<T<Ts...>, std::index_sequence<Ns...>>
{
    using tuple = std::tuple<Ts...>;
    using type =
        T<std::conditional_t<(Ns%2)==0,std::tuple_element_t<Ns/2,tuple>,space>...>;
};

template<typename T> using spacer_t = typename spacer<T>::type;

Live example

以上内容保留了您的外部容器类型,因此在您的情况下,如果您传入boost::fusion::vector&lt;...&gt;,这也是您将得到的结果(只是额外的spaces)。

【讨论】:

  • 使用 C++14,我看不到这里需要提升 - 或者我错过了您的要求之一?
  • @Hansvesselgård 嗯...如果我错过了一个要求,请为我拼写出来,不要只是重复我说的话。谢谢。
  • “使用 C++14,我看不到这里需要提升 - 或者我错过了您的要求之一?”哦,这只是来自更大代码库的一些 sn-ps,以及我制作的一些存根/虚拟代码,以便在我寻求帮助时让人们更容易理解问题。我是 TMP 的新手,所以我不知道所有正确的单词——所以我更喜欢展示我想做的事情。 "如果我遗漏了一个要求,请帮我把它拼出来,不要只是重复我说的话。谢谢"你完全理解我。
  • 非常感谢您的回答-我很惊讶。我需要一些时间才能真正理解代码。我正在观看 Walter E. Brown “现代模板元编程:纲要”,并大量阅读以更好地理解现代模板元编程。我需要了解很多概念,而对于最新的东西(例如 make_index_sequence ),我需要了解的不是很多学习辅助工具。我目前的策略是使用参数包或类型列表作为容器来实现以下算法作为模板函数,但你的做法要聪明得多,ideone.com/IPiSQm
  • @Hansvesselgård 啊,好的。好吧,在那种情况下,我很高兴能帮上忙。根据我的经验,不借助外部库(当然包括标准库),学习可变参数模板、TMP 等是值得的。在您能够充分利用更复杂的库(如 MPL 等)之前,主要要求自己了解基础知识 - 通常甚至不需要这些库,因此可以解决您在现实生活中遇到的大多数问题。
猜你喜欢
  • 1970-01-01
  • 2019-02-08
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多