2014-11-24 7 views
2

Я пытаюсь использовать алгоритм преобразования (или любую другую часть STL, которая будет выполнять задание), чтобы изменить последовательность int. Если текущий элемент больше 5, сохраните его. Else использование 5.STL алгоритм/функциональный

Это не компилируется:

std::vector<int> vec; 
vec.push_back(6); 
vec.push_back(2); 
vec.push_back(9); 
vec.push_back(4); 
vec.push_back(7); 

std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::max<int>(), 5)); 

У меня нет доступа к C++ 11.

+1

Вы не должны вызывать 'max' функцию, давая его в' станд :: bind1st'. Вы хотите дать ему функцию, а не результат вызова ее без аргументов. – chris

+0

@chris Ах, стыдно, что вы удалили свой старый (правильный) комментарий, я имею в виду это в своем ответе. ;-) –

+0

@ KonradRudolph, О, стреляй, я думал, что я сумасшедший, но я забыл, что ему нужны псевдонимы типов. Более современные инструменты делают то же самое, не навязывая это, поэтому я забыл. – chris

ответ

3

Для этой задачи более соответствующий алгоритм std::replace_if. Например

#include <iostream> 
#include <algorithm> 
#include <functional> 
#include <vector> 


int main() 
{ 
    std::vector<int> vec; 

    vec.push_back(6); 
    vec.push_back(2); 
    vec.push_back(9); 
    vec.push_back(4); 
    vec.push_back(7); 

    for (std::vector<int>::size_type i = 0; i < vec.size(); i++) 
    { 
     std::cout << vec[i] << ' '; 
    } 
    std::cout << std::endl; 

    std::replace_if(vec.begin(), vec.end(), 
        std::bind2nd(std::less<int>(), 5), 5); 

    for (std::vector<int>::size_type i = 0; i < vec.size(); i++) 
    { 
     std::cout << vec[i] << ' '; 
    } 
    std::cout << std::endl; 

    return 0; 
} 

Выход

6 2 9 4 7 
6 5 9 5 7 
+0

Это очень приятно! Именно то, что я искал, хотя мне все еще интересно, почему решение @Sebastians не работает. Спасибо Владу! –

2

Вы, к сожалению, не можете использовать bind* с указателями функций напрямую. Чтобы обойти это, вы обычно используете std::ptr_fun, но в вашем случае это не будет работать . Таким образом, путь вперед, чтобы обернуть std::max в функтор:

template <typename T> 
struct max : std::binary_function<T, T, T> { 
    T operator()(T value, T min) const { 
     return std::max(value, min); 
    } 
}; 

Использование:

std::transform(vec.begin(), vec.end(), vec.begin(), std::bind2nd(max<int>(), 5)); 

Похоже, что std::bind1st(std::ptr_fun(&std::max<int>), 5) должны работать, но, к сожалению, этот шаблон конкретизации создает две идентичные operator() перегрузки, поскольку std::max принимает свои аргументы как const.

+0

Почему нам нужен двоичный функтор? – P0W

+0

@ P0W Зажим - универсальный алгоритм. Это должна быть * общая * функция, а не одна написанная на заказ для этого вызова. Следовательно, моя 'clamp_lower' является общей функцией, которая будет использоваться с' std :: bind2nd', аналогичной использованию OP. Ваш код является полностью приемлемым ([curried] (http://en.wikipedia.org/wiki/Currying)), но он требует использования закрытия, даже если мы его не потребуем. –

+1

* «вы, к сожалению, не можете использовать bind с указателями функций» * false, это то, что 'std :: ptr_fun' для –

2

Вы можете использовать std::replace_if вместо преобразования. Это позволяет использовать предопределенный сравнительный функтор как std::less или std::greater вместо std::max:

std::replace_if(vec.begin(),vec.end(),std::bind2nd(std::less<int>(),5),5); 

Here рабочего пример.

0

Почему два существующих ответа заменяют отлично хорошо std::max с идентично реализованными функциями/функторами с разными именами? std::max отлично подходит; это то, как вы используете старые вяжущие, это неправильно.

Вы говорите, что у вас нет C++ 11. У вас есть Boost? Boost.Bind будет делать работу:.

std::transform(vec.begin(), vec.end(), vec.begin(), 
       boost::bind(&std::max<int>, _1, 5)); 

Я не могу вспомнить, что пространство имен заполнитель в

Если вы не можете использовать подталкивание либо, вы должны иметь в виду, что старые связующие нужны специальные вложенные типов из связанного функтора аргумента, а указатели на функции не имеют те, которые почему ptr_fun помощника существует:

std::transform(vec.begin(), vec.end(), vec.begin(), 
       std::bind1st(std::ptr_fun(&std::max<int>), 5)); 
+1

'std :: ptr_fun' не поможет. Он перегружает 'operator()' таким образом, что 'std :: max' делает его двумя одинаковыми перегрузками. Код также будет разбит при перемещении на C++ 11, поскольку 'std :: max ' имеет две перегрузки. – chris

+0

Согласно C++ 11 Приложение D.8.2.1 (у меня нет стандарта C++ 98), 'ptr_fun' (или, скорее,' pointer_to_binary_function', который он возвращает) не перегружает 'operator() 'вообще. Вы имеете в виду, что вызов 'ptr_fun' сам по себе неоднозначен? Если это так, то только из-за новых перегрузок 'initializer_list', которые также * * * только на C++ 11. Мой код должен отлично работать на C++ 98. –

+1

Я пробовал ваше решение, и оно действительно дало мне ошибку компиляции. Спасибо в любом случае :-) –

Смежные вопросы