вызывает что-то с константным объектом в параметре, т.е. не изменяет элементы контейнера,
А как нада писать чтобы например увеличить все эл-ты контейнера в 2 раза
skip
G>вызывает что-то с константным объектом в параметре, т.е. не изменяет элементы контейнера, G>А как нада писать чтобы например увеличить все эл-ты контейнера в 2 раза
G>вызывает что-то с константным объектом в параметре, т.е. не изменяет элементы контейнера, G>А как нада писать чтобы например увеличить все эл-ты контейнера в 2 раза
Можно просто перебрать элементы:
for (std::vector<int>::iterator ii=vec.begin(); ii!=vec.end();ii++)
{
(*ii) *= 2;
}
Либо есть еше вариант, в контейнере указатели хранить,но это уже попахивает каким-то извратом
G>вызывает что-то с константным объектом в параметре, т.е. не изменяет элементы контейнера, G>А как нада писать чтобы например увеличить все эл-ты контейнера в 2 раза
// alg_for_each.cpp
// compile with: /EHsc#include <vector>
#include <algorithm>
#include <iostream>
// The function object multiplies an element by a Factortemplate <class Type>
class MultValue
{
private:
Type Factor; // The value to multiply bypublic:
// Constructor initializes the value to multiply by
MultValue ( const Type& _Val ) : Factor ( _Val ) {
}
// The function call for the element to be multipliedvoid operator ( ) ( Type& elem ) const
{
elem *= Factor;
}
};
// The function object to determine the averageclass Average
{
private:
long num; // The number of elementslong sum; // The sum of the elementspublic:
// Constructor initializes the value to multiply by
Average ( ) : num ( 0 ) , sum ( 0 )
{
}
// The function call to process the next elmentvoid operator ( ) ( int elem ) {
num++; // Increment the element count
sum += elem; // Add the value to the partial sum
}
// return Averageoperator double ( )
{
return static_cast <double> (sum) /
static_cast <double> (num);
}
};
int main( )
{
using namespace std;
vector <int> v1;
vector <int>::iterator Iter1;
// Constructing vector v1int i;
for ( i = -4 ; i <= 2 ; i++ )
{
v1.push_back( i );
}
cout << "Original vector v1 = ( " ;
for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
cout << *Iter1 << " ";
cout << ")." << endl;
// Using for_each to multiply each element by a Factor
for_each ( v1.begin ( ) , v1.end ( ) , MultValue<int> ( -2 ) );
cout << "Multiplying the elements of the vector v1\n "
<< "by the factor -2 gives:\n v1mod1 = ( " ;
for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
cout << *Iter1 << " ";
cout << ")." << endl;
// The function object is templatized and so can be
// used again on the elements with a different Factor
for_each (v1.begin ( ) , v1.end ( ) , MultValue<int> (5 ) );
cout << "Multiplying the elements of the vector v1mod\n "
<< "by the factor 5 gives:\n v1mod2 = ( " ;
for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
cout << *Iter1 << " ";
cout << ")." << endl;
// The local state of a function object can accumulate
// information about a sequence of actions that the
// return value can make available, here the Averagedouble avemod2 = for_each ( v1.begin ( ) , v1.end ( ) ,
Average ( ) );
cout << "The average of the elements of v1 is:\n Average ( v1mod2 ) = "
<< avemod2 << "." << endl;
}
Output
Original vector v1 = ( -4 -3 -2 -1 0 1 2 ).
Multiplying the elements of the vector v1
by the factor -2 gives:
v1mod1 = ( 8 6 4 2 0 -2 -4 ).
Multiplying the elements of the vector v1mod
by the factor 5 gives:
v1mod2 = ( 40 30 20 10 0 -10 -20 ).
The average of the elements of v1 is:
Average ( v1mod2 ) = 10.
G>>вызывает что-то с константным объектом в параметре, т.е. не изменяет элементы контейнера, G>>А как нада писать чтобы например увеличить все эл-ты контейнера в 2 раза
D>
D>// alg_for_each.cpp
D>// compile with: /EHsc
D>#include <vector>
D>#include <algorithm>
D>#include <iostream>
D>// The function object multiplies an element by a Factor
D>template <class Type>
D>class MultValue
D>{
D>private:
D> Type Factor; // The value to multiply by
D>public:
D> // Constructor initializes the value to multiply by
D> MultValue ( const Type& _Val ) : Factor ( _Val ) {
D> }
D> // The function call for the element to be multiplied
D> void operator ( ) ( Type& elem ) const
D> {
D> elem *= Factor;
D> }
D>};
skip
D>int main( )
D>{
D> using namespace std;
D> vector <int> v1;
D> vector <int>::iterator Iter1;
D> // Constructing vector v1
D> int i;
D> for ( i = -4 ; i <= 2 ; i++ )
D> {
D> v1.push_back( i );
D> }
D> cout << "Original vector v1 = ( " ;
D> for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
D> cout << *Iter1 << " ";
D> cout << ")." << endl;
D> // Using for_each to multiply each element by a Factor
D> for_each ( v1.begin ( ) , v1.end ( ) , MultValue<int> ( -2 ) );
D>
D>}
D>
Вопрос, а почему это работает?
Ведь в
void MultValue::operator ( ) ( Type& elem ) const
не const Type& elem в параметре
Здравствуйте _DEBUG, Вы писали:
D>Здравствуйте gruid, Вы писали:
D>// The function object to determine the average
D>class Average
D>{
D>private:
D> long num; // The number of elements
D> long sum; // The sum of the elements
D>public:
D> // Constructor initializes the value to multiply by
D> Average ( ) : num ( 0 ) , sum ( 0 )
D> {
D> }
D> // The function call to process the next elment
D> void operator ( ) ( int elem ) {
D> num++; // Increment the element count
D> sum += elem; // Add the value to the partial sum
D> }
D> // return Average
D> operator double ( )
D> {
D> return static_cast <double> (sum) /
D> static_cast <double> (num);
D> }
D>};
Ну не стал бы я так делать. Наличие неявных преобразований, скажем так, редко упрощает понимание кода
К тому же вместо
D> // The local state of a function object can accumulate
D> // information about a sequence of actions that the
D> // return value can make available, here the Average
D> double avemod2 = for_each ( v1.begin ( ) , v1.end ( ) ,
D> Average ( ) );
Здравствуйте Bell, Вы писали:
B>Здравствуйте Pavel XP, Вы писали:
PX>> Вопрос, а почему это работает? PX>>Ведь в PX>>void MultValue::operator ( ) ( Type& elem ) const PX>>не const Type& elem в параметре
B>Ну так потому и работает B>Вот если бы было B>
Ну да, после всего этого в векторе будут десятки
PX>А как то же что этот for_each для немодифицирующихся последовательностей.
Ну во-первых в нужной функции в качестве параметра можно исплльзовать константную ссылку.
Во-вторых можно написать так:
Тогда в случае, если fff может модифицировать свой аргумент (т.е. тип аргумента — не константная ссылка), при компиляции компилятор ругнется, что позволит сделать определенные выводы...
G>вызывает что-то с константным объектом в параметре, т.е. не изменяет элементы контейнера
Насколько я понимаю, это одно из достаточно распространенных заблуждений о std::for_each, вызванное тем, что (1) в стандарте std::for_each отнесен к категории так называемых Non-modifying sequence operations, и, кроме того, (2) тем, что std::for_each требует в качестве итератора InputIterator.
Первое означает, что сам алгоритм не изменяет значения элементов последовательности, для которой он вызван, т.е., попросту говоря, не содержит фрагмента: *it = ... . Сам же функциональный объект, переданный std::for_each в качестве аргумента, вполне может, в качестве побочного эффекта, изменять значения элементов последовательности. Второе требование заключается в том, что итератор, переданный в std::for_each должен быть, как минимум, InputIterator. Ничто не запрещает передавать в std::for_each mutable итератор.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Сам же функциональный объект, переданный std::for_each в качестве аргумента, вполне может, в качестве побочного эффекта, изменять значения элементов последовательности. ... Ничто не запрещает передавать в std::for_each mutable итератор.
Вот что мне после этого интересно. Если у меня например есть map или set и в for_each я изменяю *it, то каким образом сможет этот самый for_each пройти весь контейнер по-порядку от начала до конца? Разве изменение элемента в этих типах контейнеров не модифицирует сам контейнер (порядок элементов)?
Здравствуйте WeCom, Вы писали:
ПК>>Сам же функциональный объект, переданный std::for_each в качестве аргумента, вполне может, в качестве побочного эффекта, изменять значения элементов последовательности. ... Ничто не запрещает передавать в std::for_each mutable итератор.
WC>Вот что мне после этого интересно. Если у меня например есть map или set и в for_each я изменяю *it, то каким образом сможет этот самый for_each пройти весь контейнер по-порядку от начала до конца? Разве изменение элемента в этих типах контейнеров не модифицирует сам контейнер (порядок элементов)?
Итераторы std::map не позволяют изменять ключи, т.к. при разыменовании дают std::pair<const Key, const Type>&. Итераторы std::set не позволяют изменять элементы std::set, т.е. не являются mutable iterators. Даже в тех реализациях STL, которые не приняли к сведению соответствующее сообщение о дефекте в стандарте, и в которых итераторы множества позволяют изменять элементы контейнера, изменение элементов, приводящее к изменению порядка, нарушает целостность контейнера. Так что, нет, ты не сможешь изменить порядок элементов в контейнерах std::set и std::map, изменив значение элемента в функциональном объекте, переданном в std::for_each.
Однако, конечно, можно помешать работе std::for_each, добавив в std::vector какое-то количество элементов и нарушив целостность итераторов в процессе выполнения алгоритма. Что ж, здравый смысл никто не отменял...
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VK>>Либо есть еше вариант, в контейнере указатели хранить,но это уже попахивает каким-то извратом
...>Вышеприведенный код тоже попахивает извратом. Есть же готовые алгоритмы для этого:
...>
Да, но в случае множества простых,не связанных и выполняемых однократно изменений элементов контейнера получаем либо огромное количество простых функций либо функцию с большим свитчем, что уже не очень хорошо.
VK>Да, но в случае множества простых,не связанных и выполняемых однократно изменений элементов контейнера получаем либо огромное количество простых функций либо функцию с большим свитчем, что уже не очень хорошо.
Возникает вопрос: а зачем нужны эти "простые, не связанные и выполняемые однократно изменения элементов контейнера"? Первое впечатление — ошибка проектирования.
VK>Да, но в случае множества простых,не связанных и выполняемых однократно изменений элементов контейнера получаем либо огромное количество простых функций либо функцию с большим свитчем, что уже не очень хорошо.
Кстати, чем это плохо? Ведь "огромное количество простых функций" очень хорошо заинлайнится. А если использовать lambda library, то их вообще выписывать отдельно не надо будет.
Здравствуйте Pavel XP, Вы писали:
PX> Вопрос, а почему это работает? PX>Ведь в PX>void MultValue::operator ( ) ( Type& elem ) const PX>не const Type& elem в параметре
А кто сказал, что там должно быть const в параметре?