STL transform algorithm

P

Patrick Guio

Dear all,

I am trying to use the std::transform algorithm to to the following

vector< vector<char> >::iterator ik = keys.begin(); // key list iterator
vector< vector<char> >::iterator is = ik; // save begin
[snip]
vector<char>::const_iterator i = ik->begin();
vector<char>::const_iterator e = ik->end();
vector<char>::iterator s = is->begin();
for ( ; i != e; i++, s++) { // xor the key s = s ^ k
*s ^= *i;
}

I wrote the binary operator xor

template <class _Tp>
struct logical_xor : public std::binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{
return __x ^ __y;
}
};

and call it into the transform algorithm

// run through the ik iterator (input1) and is iterator (input2) and
// return into is (output)
std::transform(ik->begin(), ik->end(), is->begin(), is->begin(), logical_xor<byte>());

But it does not seem to work correctly.
Can input2 and output iterator be the same? (i.e. perform the operation
(output =) input2 = op(input1, input2)
Is there a way to perform operation and assignement ^= operator instead?
(i.e. perform the operation (output =) input2 op= input1

Sincerely,

Patrick
 
?

=?ISO-8859-1?Q?Stefan_N=E4we?=

Patrick said:
Dear all,

I am trying to use the std::transform algorithm to to the following

vector< vector<char> >::iterator ik = keys.begin(); // key list
iterator
vector< vector<char> >::iterator is = ik; // save begin
[snip]
vector<char>::const_iterator i = ik->begin();
vector<char>::const_iterator e = ik->end();
vector<char>::iterator s = is->begin();
for ( ; i != e; i++, s++) { // xor the key s = s ^ k
*s ^= *i;
}

I wrote the binary operator xor

template <class _Tp>
struct logical_xor : public std::binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{
return __x ^ __y;
}
};

and call it into the transform algorithm

// run through the ik iterator (input1) and is iterator (input2) and //
return into is (output)
std::transform(ik->begin(), ik->end(), is->begin(), is->begin(),
logical_xor<byte>());

But it does not seem to work correctly.
Can input2 and output iterator be the same? (i.e. perform the operation
(output =) input2 = op(input1, input2)
Is there a way to perform operation and assignement ^= operator instead?
(i.e. perform the operation (output =) input2 op= input1


Just a question: What's the sense of assigning the (bool) result of x XOR y into x ?
Or am I missing something?

Stefan
 
B

Bob Hairgrove

Dear all,

I am trying to use the std::transform algorithm to to the following

vector< vector<char> >::iterator ik = keys.begin(); // key list iterator
vector< vector<char> >::iterator is = ik; // save begin
[snip]
vector<char>::const_iterator i = ik->begin();
vector<char>::const_iterator e = ik->end();
vector<char>::iterator s = is->begin();
for ( ; i != e; i++, s++) { // xor the key s = s ^ k
*s ^= *i;
}

I wrote the binary operator xor

template <class _Tp>
struct logical_xor : public std::binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{
return __x ^ __y;
}
};

and call it into the transform algorithm

// run through the ik iterator (input1) and is iterator (input2) and
// return into is (output)
std::transform(ik->begin(), ik->end(), is->begin(), is->begin(), logical_xor<byte>());

But it does not seem to work correctly.
Can input2 and output iterator be the same? (i.e. perform the operation
(output =) input2 = op(input1, input2)
Is there a way to perform operation and assignement ^= operator instead?
(i.e. perform the operation (output =) input2 op= input1

Sincerely,

Patrick

You cannot change either of the input vectors. The next-to-last
argument should refer to another vector which is filled with the
results of the logical_xor. So you need to initialize a third vector
with the same size as the range you are working on (in this case,
since you pass begin() and end(), the same size as the whole input
vectors).

Aside from that, you seem to have problems with the binary function.

First of all, you should never use the names beginning with an
underscore because these are reserved for the library.

Secondly, your class inherits from a concrete specialization of a
template class; it is not a template class!

Thirdly, your function needs to return char (not bool), which is what
the vectors are declared to contain.

Something like this should work:

struct logical_xor : public std::binary_function< char, char, char >
{
char operator()(const char& x, const char& y) const
{
return x ^ y;
}
};

I didn't test this, however.
 
?

=?ISO-8859-1?Q?Stefan_N=E4we?=

Bob said:
Dear all,

I am trying to use the std::transform algorithm to to the following

vector< vector<char> >::iterator ik = keys.begin(); // key list iterator
vector< vector<char> >::iterator is = ik; // save begin
[snip]
vector<char>::const_iterator i = ik->begin();
vector<char>::const_iterator e = ik->end();
vector<char>::iterator s = is->begin();
for ( ; i != e; i++, s++) { // xor the key s = s ^ k
*s ^= *i;
}

I wrote the binary operator xor

template <class _Tp>
struct logical_xor : public std::binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{
return __x ^ __y;
}
};

and call it into the transform algorithm

// run through the ik iterator (input1) and is iterator (input2) and
// return into is (output)
std::transform(ik->begin(), ik->end(), is->begin(), is->begin(), logical_xor<byte>());

But it does not seem to work correctly.
Can input2 and output iterator be the same? (i.e. perform the operation
(output =) input2 = op(input1, input2)
Is there a way to perform operation and assignement ^= operator instead?
(i.e. perform the operation (output =) input2 op= input1

Sincerely,

Patrick


You cannot change either of the input vectors. The next-to-last
argument should refer to another vector which is filled with the
results of the logical_xor. So you need to initialize a third vector
with the same size as the range you are working on (in this case,
since you pass begin() and end(), the same size as the whole input
vectors).


From '25.2.3 Transform [lib.alg.transform]':

....
5 Notes: result may be equal to first in case of unary transform, or to first1 or first2 in
case of binary transform.


Aside from that, you seem to have problems with the binary function.

First of all, you should never use the names beginning with an
underscore because these are reserved for the library.

Secondly, your class inherits from a concrete specialization of a
template class; it is not a template class!

Thirdly, your function needs to return char (not bool), which is what
the vectors are declared to contain.

ACK.


Stefan
 
B

Bob Hairgrove

From '25.2.3 Transform [lib.alg.transform]':

...
5 Notes: result may be equal to first in case of unary transform, or to first1 or first2 in
case of binary transform.

Thanks for this. I'm glad to know that the standard allows it. I was
reading documentation from an older version of MSDN, which I shouldn't
have done...but I was too lazy to get my heavy standards book off the
shelf! Now I'll know better

Here's what the MSDN for VS 6.0 says:

"transform
template<class InIt, class OutIt, class Unop>
OutIt transform(InIt first, InIt last, OutIt x, Unop uop);
template<class InIt1, class InIt2, class OutIt, class Binop>
OutIt transform(InIt1 first1, InIt1 last1, InIt2 first2,
OutIt x, Binop bop);
The first template function evaluates *(x + N) = uop(*(first + N))
once for each N in the range [0, last - first). It then returns x +
(last - first). The call uop(*(first + N)) must not alter *(first +
N).

The second template function evaluates *(x + N) = bop(*(first1 + N),
*(first2 + N)) once for each N in the range [0, last1 - first1). It
then returns x + (last1 - first1). The call bop(*(first1 + N),
*(first2 + N)) must not alter either *(first1 + N) or *(first2 + N)."
^^^^^^^^^^^^^^

I'm glad they have caught up with the standard here.
 
S

Stefan =?UTF-8?B?TsOkd2U=?=

Patrick said:
On Wed, 2 Nov 2005, Bob Hairgrove wrote:

Hello Bob,




Oops my fault, I did grab the template class (too quickly obviously) from
logical_or in (||) <algorithm> which is not the bitwise or operator (|)

I don't want to loose generality and it looks like it works well
with the following definition

template <class _Tp>
struct logical_xor : public std::binary_function<_Tp, _Tp, _Tp>
{
_Tp
operator()(const _Tp& __x, const _Tp& __y) const
{
return _Tp(__x ^ __y);
}
};

as mentionned in another email the specification transform
allow output to be the same iterator as input2.

But I still wonder whether / how could I make use of the biwise and
assignement in one operator a ^= b instead of a = a ^ b?

What about this:

//---------------------------------
// apply a BinOp to each item of two ranges
template<typename It1, typename It2, typename BinOp>
BinOp for2(It1 f1, It1 l1, It2 f2, BinOp bop)
{
for ( ; f1 != l1; ++f1, ++f2)
bop(*f1, *f2);

return bop;
}

// do __x ^= __y
template <class _Tp>
struct xor_assign : public std::binary_function<_Tp, _Tp, void>
{
void
operator()(_Tp& __x, const _Tp& __y) const
{
__x ^= __y;
}
};

string s1 = "ABCD";
string s2 = "EFGH";

for2(s1.begin(), s1.end(), s2.begin(), xor_assign<char>());
//---------------------------------

A quick test gave me a sensible result.

HTH

Stefan
--
 
P

Patrick Guio

On Wed, 2 Nov 2005, Bob Hairgrove wrote:

Hello Bob,


First of all, you should never use the names beginning with an
underscore because these are reserved for the library.

Secondly, your class inherits from a concrete specialization of a
template class; it is not a template class!

Thirdly, your function needs to return char (not bool), which is what
the vectors are declared to contain.

Oops my fault, I did grab the template class (too quickly obviously) from
logical_or in (||) <algorithm> which is not the bitwise or operator (|)

I don't want to loose generality and it looks like it works well
with the following definition

template <class _Tp>
struct logical_xor : public std::binary_function<_Tp, _Tp, _Tp>
{
_Tp
operator()(const _Tp& __x, const _Tp& __y) const
{
return _Tp(__x ^ __y);
}
};

as mentionned in another email the specification transform
allow output to be the same iterator as input2.

But I still wonder whether / how could I make use of the biwise and
assignement in one operator a ^= b instead of a = a ^ b?

Any idea?

Sincerely,

Patrick
 
B

Bob Hairgrove

// do __x ^= __y
template <class _Tp>
struct xor_assign : public std::binary_function<_Tp, _Tp, void>
{
void
operator()(_Tp& __x, const _Tp& __y) const
{
__x ^= __y;
}
};

You should never use names with leading underscores -- see 17.4.3.1.2
of the standard.
 
D

deane_gavin

Bob said:
You should never use names with leading underscores -- see 17.4.3.1.2
of the standard.

Or names with double underscores anywhere in the name.

Gavin Deane
 
C

Clark S. Cox III

From '25.2.3 Transform [lib.alg.transform]':

...
5 Notes: result may be equal to first in case of unary transform, or to
first1 or first2 in
case of binary transform.

Thanks for this. I'm glad to know that the standard allows it. I was
reading documentation from an older version of MSDN, which I shouldn't
have done...but I was too lazy to get my heavy standards book off the
shelf! Now I'll know better

Here's what the MSDN for VS 6.0 says:

"transform
template<class InIt, class OutIt, class Unop>
OutIt transform(InIt first, InIt last, OutIt x, Unop uop);
template<class InIt1, class InIt2, class OutIt, class Binop>
OutIt transform(InIt1 first1, InIt1 last1, InIt2 first2,
OutIt x, Binop bop);
The first template function evaluates *(x + N) = uop(*(first + N))
once for each N in the range [0, last - first). It then returns x +
(last - first). The call uop(*(first + N)) must not alter *(first +
N).

The second template function evaluates *(x + N) = bop(*(first1 + N),
*(first2 + N)) once for each N in the range [0, last1 - first1). It
then returns x + (last1 - first1). The call bop(*(first1 + N),
*(first2 + N)) must not alter either *(first1 + N) or *(first2 + N)."
^^^^^^^^^^^^^^

I'm glad they have caught up with the standard here.

You're misreading the MSDN documentation as well. That last sentence of
each paragraph simply says that the _functor itself_ mustn't alter the
values, not that std::transform won't do so.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top