Ваше явление может быть сведено к простому, хотя и загадочному примеру:
MY_OUTPUT := First line
.PHONY: foo
foo:
@echo $(MY_OUTPUT)
$(eval MY_OUTPUT := $(shell $(info eval-time) echo Second line))
@echo $(MY_OUTPUT)
$(shell read -p "Hit return:")
Вывод:
$ make foo
eval-time
Hit return:
... в ожидании нажатия клавиши [117 ]
blockquote>First line Second line
Оценка рецепта выглядит следующим образом: Выделите буфер строк, которые будут содержать командные строки окончательного рецепта без синтаксиса make. Затем пройдитесь по всем строкам рецепта, выполните весь известный синтаксис make, удалите один уровень из всех кавычек (
$
), выполните вещи$(eval)
и запишите строки в буфер. только затем перебирают результирующий список командных строк и выдают ихsh
по очереди.$(info)
говорит нам, что строка аргумента уже была оценена заранее, что нарушает ваш предполагаемый порядок.
Я озирался и нашел boost::transform_iterator
. Я придумал этот код. Удивление, как хорошо это работает:
#include <map>
#include <algorithm>
#include <iostream>
#include <string>
#include <iterator>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
int main() {
typedef std::map<std::string, int>::value_type value_type;
std::map<std::string, int> a;
a["one"] = 1;
a["two"] = 2;
// returns the second element
boost::function<int(value_type&)> f = boost::bind(&value_type::second, _1);
std::copy(boost::make_transform_iterator(a.begin(), f),
boost::make_transform_iterator(a.end(), f),
std::ostream_iterator<int>(std::cout, " "));
}
Это печатает "1 2 "
к стандартному выводу.
Нет никакого умного решения остроты. Ваша лучшая надежда состоит в том, чтобы записать итератор обертки. Это - на самом деле довольно каноническое решение. Вы могли бы проверить, имеет ли Повышение уже то, в чем Вы нуждаетесь. В противном случае попытайтесь записать универсальную обертку, которая может быть снова использована для других проблем.
STL содержит такую названную обертку итератора reverse_iterator
. Имя подразумевает свое использование.
Можно разделить на подклассы, например, станд.:: вектор:: const_iterator самостоятельно, повторно реализовывая оператор* и оператор-> для возврата первой из пары. Необходимо было бы также создать собственное, начинаются () и конец () функции для возврата пользовательского итератора.
Можно также создать к классам двоичной функции и передать тех, которые к inner_product.
В конечном счете я думаю, что Ваша идея является способом пойти. Можно использовать Повышение, чтобы помочь Вам сделать это. Для запуска Вам была бы нужна функция, которая берет Вашу пару и возвращает первый элемент. Я думаю, что Вы могли записать такое функциональное встроенное пользование библиотекой Lambda, но для пользы удобочитаемости, я думаю, что просто записал бы простую функцию, которая делает это вместо этого. Затем передача, которые функционируют с Вашими исходными итераторами для построения a transform_iterator
поскольку Ваша последовательность начинается и заканчивается.