2015-06-06 3 views
4

У меня есть этот классMPL заменить без литья слитого контейнера

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, чтобы получить доступ к его переменным детям члена.

Тип childListType - это класс, который наследуется от boost :: fusion :: vector.

Я хотел бы программным образом сделать переменную-члену children содержать один пробел между каждой строкой.

Так что, если я вхожу:

<string,string> 

детей становится:

<string, space,string> 

Если я вхожу:

<string,string,string> 

становится

<string,space,string,space,string> 

т.д.

Я использую повысить фьюжн поэтому должны быть во время компиляции.

Я попытался сделать это следующим образом:

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: заменить изменяет тип контейнера из моего собственного класса, который наследуется от повышающего :: фьюжн :: вектор, к 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) 
+0

Не понимайте, почему бы просто не добавить пробелы в точке, где вы вытесняете все - если вы знаете, что каждый элемент должен быть разделен пробелом? Также я предполагаю, что ваша потоковая функциональность сломана, если вы не можете обрабатывать * кортежи * разных размеров? – Nim

+0

Код, который я вставил здесь, должен только показать концепцию, которую я хочу решить. –

+0

На самом деле не просто получить его, чтобы вывести правильную вещь - я начинаю изучать MPL и застрял здесь, поэтому я надеялся, что кто-то может сказать что-то вроде «о, вам просто нужно использовать boost :: XXXXX вместо» или показать меня в правильном направлении. –

ответ

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 s).

+0

С C++ 14, я не вижу необходимости в повышении здесь - или, может быть, мне не хватает одного из ваших требований? –

+0

@ Hansvesselgård Ум ... если я пропустил требование, то, пожалуйста, напишите мне, не повторяйте, что я сказал. Благодарю. –

+0

«С C++ 14 я не вижу необходимости в усилении здесь - или, может, мне не хватает одного из ваших требований?» О, это всего лишь некоторые фрагменты из большей базы кода и с некоторым кодом заглушки/фиктивного кода, который я сделал для облегчения понимания людьми проблемы, когда я прошу о помощи. Я новичок в TMP, поэтому не знаю всех правильных слов, поэтому я предпочитаю показывать, что я хочу делать. «Если бы я пропустил какое-то требование, то, пожалуйста, напишите мне, не просто повторите то, что я сказал. Спасибо:« Ты прекрасно меня понял. –