I have this class
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;
}
};
it uses CRTP to allow the HaveChildren class to access its children member variable.
The childrenListType is a class that inherits from boost::fusion::vector.
I would like to programmatically make the children member variable contain one space class between each string.
So if I enter:
<string,string>
children becomes:
<string, space,string>
If I enter:
<string,string,string>
it becomes
<string,space,string,space,string>
etc.
I am using boost fusion so it have to be at compile time.
I have tried to do it like this:
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;
}
};
But then the MPL:replace changes the type of the container from my own class, that inherits from boost::fusion::vector, to a boost::fusion::vector4 and that ruins my streaming overloaders.
You may notice that instead of having <string,space>
I replace each string with a stringAndSpace
.
Having <string,space>
would be best- but the other way was easier for me.
So- to summarise:
typedef boost::mpl::replace< context, string, stringAndSpace >::type replacedContext;
casts my container type- can you help to make a function that can at compile time define a type be the following class
struct childrenListType : public boost::fusion::vector<CHILDREN_TYPES...>
with template arguments of one space between every string I input?
I have posted the full source at: http://ideone.com/XxYTOt
Their compilers typeinfo says that without the mpl replace the children type is: 16childrenListTypeIISsSsSsSsEE
and with : N5boost6fusion7vector4I14stringAndSpaceS2_S2_S2_EE
You can also see the stream overloads fails because it outputs the parenthesis around:
(this sentence needs spaces )
With C++14, I fail to see the need for boost here - or maybe I'm missing one of your requirements? The following will add spaces between the types with plain 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;
The above preserves your outer container type, so in your case if you pass in a boost::fusion::vector<...>
, this is also what you'll get as a result (just with additional space
s).