копировать:

аюсь создать свой собственныйboost::adaptors::transformed.

Вот связанныйповысить код.

Вот его использование (изменено сТАК ответ от LogicStuff): -

C funcPointer(B& b){ 
    //"funcPointer" is function convert from "B" to "C"
    return instance-of-C
}

MyArray<B> test;  //<-- any type, must already have begin() & end()

for(C c : test | boost::adaptor::transformed(funcPointer)) {
    //... something ....
}

Результат будет таким же, как: -

for(auto b : test) {
    C c = funcPointer(b);
    //... something ...
}
Моя попытка

я создалCollectAdapter которые стремятся работать какboost::adaptor::transformed.
Это работает нормально в большинстве распространенных случаев.

Вот полныйдемонстрация а такжерезервное копирование. (такой же, как приведенный ниже код)

Проблемная частьCollectAdapter - ядро ​​моей библиотеки.
Я не знаю, должен ли я кешироватьcollection_ по-указатель или жепо значению.

CollectAdapter заключает в себе основуcollection_ (например, указатель наstd::vector<>): -

template<class COLLECTION,class ADAPTER>class CollectAdapter{
    using CollectAdapterT=CollectAdapter<COLLECTION,ADAPTER>;
    COLLECTION* collection_;    //<---- #1  problem? should cache by value?
    ADAPTER adapter_;           //<---- = func1 (or func2)
    public: CollectAdapter(COLLECTION& collection,ADAPTER adapter){
        collection_=&collection;
        adapter_=adapter;
    }
    public: auto begin(){
        return IteratorAdapter<
            decltype(std::declval<COLLECTION>().begin()),
            decltype(adapter_)>
            (collection_->begin(),adapter_);
    }
    public: auto end(){ ..... }
};

IteratorAdapter (используется выше) инкапсулирует базовый итератор, изменяет поведениеoperator* : -

template<class ITERATORT,class ADAPTER>class IteratorAdapter : public ITERATORT {
    ADAPTER adapter_;
    public: IteratorAdapter(ITERATORT underlying,ADAPTER adapter) :
        ITERATORT(underlying),
        adapter_(adapter)
    {   }
    public: auto operator*(){
        return adapter_(ITERATORT::operator*());
    }
};

CollectAdapterWidget (используется ниже) это просто вспомогательный класс для построенияCollectAdapter-пример.

Может использоваться как:

int func1(int i){   return i+10;   }
int main(){
    std::vector<int> test; test.push_back(5);
    for(auto b:CollectAdapterWidget::createAdapter(test,func1)){
        //^ create "CollectAdapter<std::vector<int>,func1>" instance
         //here, b=5+10=15
    }
}  
проблема

Приведенный выше код работает нормально в большинстве случаев, кроме случаев, когдаCOLLECTION это временный объект.

В частности, когда я создаюадаптер адаптера адаптера ....

int func1(int i){   return i+10;    }
int func2(int i){   return i+100;   }
template<class T> auto utilityAdapter(const T& t){
    auto adapter1=CollectAdapterWidget::createAdapter(t,func1);
    auto adapter12=CollectAdapterWidget::createAdapter(adapter1,func2);
    //"adapter12.collection_" point to "adapter1"
    return adapter12;
    //end of scope, "adapter1" is deleted
    //"adapter12.collection_" will be dangling pointer
}
int main(){
    std::vector<int> test;
    test.push_back(5);
    for(auto b:utilityAdapter(test)){
        std::cout<< b<<std::endl;   //should 5+10+100 = 115
    }
}

Это приведет к ошибке во время выполнения. Вотдемо-свисающий указатель.

В реальном использовании, если интерфейс более удивительный, например, использование| Оператор, ошибка будет еще сложнее обнаружить: -

//inside "utilityAdapter(t)"
return t|func1;        //OK!
return t|func1|func2;  //dangling pointer
Вопрос

Как улучшить мою библиотеку, чтобы исправить эту ошибку, сохраняяспектакль & прочность & maintainablilty на том же уровне?

Другими словами, как кэшировать данные или указательCOLLECTION (это может бытьадаптер или жереальная структура данных) элегантно?

В качестве альтернативы, если легче ответить путем кодирования с нуля (чем модифицировать мой код), сделайте это. :)

Мои обходные пути

Текущий код кешейпо указателю.
Основная идея обходных путей заключается в кешированиипо значению вместо.

Обходной путь 1 (всегда «по значению»)

Позволятьадаптер кэшироватьзначение изCOLLECTION.
Вот главное изменение:

COLLECTION collection_;    //<------ #1 
//changed from   .... COLLECTION* collection_;

Недостаток:-

Вся структура данных (например,std::vector) будет скопировано значение - ненужный ресурс.
(при использовании дляstd::vector напрямую)Обходной путь 2 (две версии библиотеки, лучше?)

Я создам 2 версии библиотеки -AdapterValue а такжеAdapterPointer.
Я должен создать связанные классы (Widget,AdapterIteratorи т. д.)

AdapterValue - по значению, (предназначен дляutilityAdapter())AdapterPointer - по указателю, (предназначен дляstd::vector)

Недостаток:-

Много повторяющегося кода = низкая ремонтопригодностьПользователи (кодеры) должны очень хорошо понимать, какой из них выбрать = низкая надежностьОбходной путь 3 (определить тип)

Я могу использовать специализацию шаблона, которая делает это:

If( COLLECTION is an "CollectAdapter" ){ by value }  
Else{ by pointer }    

Недостаток:-

Не очень хорошо взаимодействует между многими классами адаптеров.
Они должны узнать друг друга:признанное = должен кешироватьпо значению.

Извините за очень длинный пост.

Ответы на вопрос(1)

Ваш ответ на вопрос