MPL替换而不铸造融合容器

时间:2015-06-06 17:52:12

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

我有这个班级

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。

的类

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

所以,如果我输入:

<string,string>
孩子们成了:

<string, space,string>

如果我输入:

<string,string,string>

它变成了

<string,space,string,space,string>

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

我试过这样做:

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,这会破坏我的流式上传器。

您可能会注意到我没有<string,space>而是用stringAndSpace替换每个字符串。

<string,space>最好 - 但另一种方式对我来说更容易。

总结一下:

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 )

1 个答案:

答案 0 :(得分:2)

使用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<...>,这也是你得到的结果(只需要额外的space)。< / p>