Write a transform_until template

S

silverburgh.meryl

Hi,
I am trying to write a transform_until template. It is bascially doing
what transform is doing except if UnaryOperation return NULL, it will
break out from the loop.

Here is the code, but it has compile error, can you please tell me what
did I do wrong?

template <class _InputIter, class _OutputIter, class _UnaryOperation>
_OutputIter
transform_until (_InputIter __first, _InputIter __last, _OutputIter
__res,
_UnaryOperation __unary_op)
{


for (; !(__first == __last); ++__res, ++__first) {
// this line does not compile:
_OutputIter::value_type obj = __unary_op (*__first);

if (obj != NULL) {
*__res = obj;
} else {
return __res;
}

}
return __res;
}

Here is the compile error:
.../Utils.h: In function '_OutputIter transform_until(_InputIter,
_InputIter, _OutputIter, _UnaryOperation)':
.../Utils.h:88: error: expected `;' before 'obj'
.../Utils.h:90: error: 'obj' was not declared in this scope
 
V

Victor Bazarov

> [..]
// this line does not compile:
_OutputIter::value_type obj = __unary_op (*__first);

typename _OutputIter:: ...

And don't use names that begin with an underscore and a capital letter,
they are reserved by the implementation.

V
 
M

Michiel.Salters

Victor said:
[..]
// this line does not compile:
_OutputIter::value_type obj = __unary_op (*__first);

typename _OutputIter:: ...

And don't use names that begin with an underscore and a capital letter,
they are reserved by the implementation.

As are names containing two adjacent _ _ at any position.

Regards,
Michiel Salters
 
D

Dietmar Kuehl

Here is the code, but it has compile error, can you please tell me what
did I do wrong?

Lots of things...
template <class _InputIter, class _OutputIter, class _UnaryOperation>
_OutputIter
transform_until (_InputIter __first, _InputIter __last, _OutputIter
__res,
_UnaryOperation __unary_op)

First of all, all names starting with an underscore followed by
a capital letter or containing two adjacent underscores are
reserved for the implementation in all contexts. That is, *all*
of the names used above are reserved and shall not be used! I'd
guess you have just copied this style from one of the standard
library's headers. Note, however, that these headers are not
intended for teaching and copying code from there might even be
considered a copyright violation.
{


for (; !(__first == __last); ++__res, ++__first) {

The return type of comparing two iterators for equality has to
be convertible to 'bool' but is not required to be 'bool'. Thus,
the above condition should be written as

!bool(first == last)

This error is quite common even in standard library implementations,
however. On the other hand, I don't think that any of the standard
library implementers is really willing to fix it...
// this line does not compile:
_OutputIter::value_type obj = __unary_op (*__first);

The 'value_type' is a dependent name and thus require qualification
with the 'typename' keyword:

typename OutputIterator::value_type obj = unary_op(*first);

However, iterators are not required to provide any nested typedefs
as this is e.g. impossible to achieve when using pointers. Thus,
the class template 'iterator_traits' is used to infer types
associated with iterators. In addition, true output iterators
define their value type as 'void' causing yet another problem. Thus,
the above line shall actually read

typename std::iterator_traits<InputIterator>::value_type obj
= unary_op(*first);

(assuming, of course, that I have not introduced a type into the
above statement).
 
R

roberts.noah

Dietmar said:
The return type of comparing two iterators for equality has to
be convertible to 'bool' but is not required to be 'bool'. Thus,
the above condition should be written as

!bool(first == last)

C-Style cast? Hmmm...
 
V

Victor Bazarov

Dietmar Kuehl wrote:




C-Style cast? Hmmm...

It's not. It's called "explicit type conversion (functional notation)".
A C-style cast ("explicit type conversion (cast notation)") would be

!(bool)(first == last)

V
 
D

Dietmar Kuehl

C-Style cast? Hmmm...

No, just an explicit conversion: this explicitly constructs a temporary
of type 'bool' initialized with the [possibly converted] result of
'first == last'. The above syntax is not permitted in C at all. A
C-style cast would look like this: '(bool)(first == last)'.
 
R

roberts.noah

Dietmar said:
C-Style cast? Hmmm...

No, just an explicit conversion: this explicitly constructs a temporary
of type 'bool' initialized with the [possibly converted] result of
'first == last'. The above syntax is not permitted in C at all. A
C-style cast would look like this: '(bool)(first == last)'.

"If the expression list is a single expression, the type conversion
expression is equivalent (in definednedd, and if defined in meaning) to
the corresponding cast expression."

In other words there is no functional difference between bool(expr) and
(bool)(expr).

Also, I believe you are wrong about C but I can't recall for sure.
 
T

TB

(e-mail address removed) skrev:
Dietmar said:
Dietmar Kuehl wrote:
The return type of comparing two iterators for equality has to
be convertible to 'bool' but is not required to be 'bool'. Thus,
the above condition should be written as

!bool(first == last)
C-Style cast? Hmmm...
No, just an explicit conversion: this explicitly constructs a temporary
of type 'bool' initialized with the [possibly converted] result of
'first == last'. The above syntax is not permitted in C at all. A
C-style cast would look like this: '(bool)(first == last)'.

"If the expression list is a single expression, the type conversion
expression is equivalent (in definednedd, and if defined in meaning) to
the corresponding cast expression."

In other words there is no functional difference between bool(expr) and
(bool)(expr).

Also, I believe you are wrong about C but I can't recall for sure.

int main() {
int a = 0;
int b = int(a);
return 0;
}

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C99

"ComeauTest.c", line 3: error: expected an expression
int b = int(a);
^

1 error detected in the compilation of "ComeauTest.c".
 
D

Dietmar Kuehl

"If the expression list is a single expression, the type conversion
expression is equivalent (in definednedd, and if defined in meaning) to
the corresponding cast expression."

Of course, it is! The C-style even happens to do this right thing for
many cases. E.g. if 'static_cast<T>(expr)' is a valid choice, the
C-style cast has exactly the same semantics as the above! In fact,
the C-style cast per se is not really that bad. What is bad about it
is that it may have the same meaning as 'reinterpret_cast<T>(expr)'
if no other suitable cast is available. However, the same does not
apply to explicit conversions a la 'bool(expr)': these are always
equivalent to 'static_cast said:
In other words there is no functional difference between bool(expr) and
(bool)(expr).

OK. ... and? Nor is there is a function difference with any of the
other alternatives like 'static_cast said:
Also, I believe you are wrong about C but I can't recall for sure.

I'm pretty sure that C does not support function style casts.
 
A

Alf P. Steinbach

* Dietmar Kuehl:
Of course, it is! The C-style even happens to do this right thing for
many cases. E.g. if 'static_cast<T>(expr)' is a valid choice, the
C-style cast has exactly the same semantics as the above! In fact,
the C-style cast per se is not really that bad. What is bad about it
is that it may have the same meaning as 'reinterpret_cast<T>(expr)'
if no other suitable cast is available. However, the same does not
apply to explicit conversions a la 'bool(expr)': these are always
equivalent to 'static_cast<T>(expr)'.

Re the last sentence above: are you sure?

int main()
{
typedef char* CharPtr;

int* p = 0;
char* q1 = CharPtr( p );
char* q2 = static_cast<CharPtr>( p );
}

Don't know what you mean by "à la", but for q1 you have what various
compilers say is an OK reinterpret_cast, whereas for q2 you have what
the same compilers say is an invalid static_cast.

I'm pretty sure :)-)) the standard says the same thing, but have so many
windows up and and running that Acrobat would be just too much.

OK. ... and? Nor is there is a function difference with any of the
other alternatives like 'static_cast<bool>(expr)'.

I think Noah's point here relates to earlier discussion, where the
C-style of the cast was cast in doubt... ;-)
 
D

Daniel T.

Hi,
I am trying to write a transform_until template. It is bascially doing
what transform is doing except if UnaryOperation return NULL, it will
break out from the loop.

Here is the code, but it has compile error, can you please tell me what
did I do wrong?

template <class _InputIter, class _OutputIter, class _UnaryOperation>
_OutputIter
transform_until (_InputIter __first, _InputIter __last, _OutputIter
__res,
_UnaryOperation __unary_op)
{


for (; !(__first == __last); ++__res, ++__first) {
// this line does not compile:
_OutputIter::value_type obj = __unary_op (*__first);

if (obj != NULL) {
*__res = obj;
} else {
return __res;
}

}
return __res;
}

Even if the above worked, IMHO it's not a good idea. It would be
impossible to transform int's to 0 using it. Better would be something
like this (IMO.)

transform( first1, find_if( first1, last1, pred ), first2, op );

Where, first1 and last1 are iterators in a range, and first2 is an
iterator in a different range. 'pred' returns true if applying 'op' to
the element would return NULL (and may even use 'op' in its
implementation,) and 'op' does the actual transformation.
 
R

roberts.noah

Dietmar said:
Of course, it is! The C-style even happens to do this right thing for
many cases. E.g. if 'static_cast<T>(expr)' is a valid choice, the
C-style cast has exactly the same semantics as the above! In fact,
the C-style cast per se is not really that bad. What is bad about it
is that it may have the same meaning as 'reinterpret_cast<T>(expr)'
if no other suitable cast is available. However, the same does not
apply to explicit conversions a la 'bool(expr)': these are always
equivalent to 'static_cast<T>(expr)'.

But now you are mixing styles. Much better to use one or the other.
Otherwise you have to remember to use one when you can and the other
when you can't (or shouldn't) and this is messy. Better to use new
style even when C-Style is guaranteed to work as expected.
OK. ... and? Nor is there is a function difference with any of the
other alternatives like 'static_cast<bool>(expr)'.

Well, static_cast is easier to find. I don't see a whole lot of
difference in grepability of XX(XXX) vs (XX)(XXX). In fact if you
where trying to find all casts in a project function style might be
MORE difficult to establish as it looks like a function call. Only
times when it would work at all is when you want to find a cast to a
specific type. Compare vs. "static_cast" is going to turn up any
static cast to any type at all (and possibly some comments). So they
are actually not functionally equivelent.

Also, bool(expr) could cast away constness unexpectedly just as C-Style
can. New style can't so again, not functionally equivelent.
 
D

Dietmar Kuehl

Daniel said:
Even if the above worked, IMHO it's not a good idea. It would be
impossible to transform int's to 0 using it. Better would be something
like this (IMO.)

transform( first1, find_if( first1, last1, pred ), first2, op );

Note, however, that this approach does not work for input iterators:
the corresponding sequence can only be traversed once. However, I
would separate the transformation and the predicate, too.
 
D

Dietmar Kuehl

Alf said:
* Dietmar Kuehl:

Re the last sentence above: are you sure?

Since 'bool(expr)' is obviously not equivalent to
'static_cast<T>(expr)', I'm not quite sure :) If the 'T' is
replaced by 'bool', however, I'm quite sure they are. ... and this
is definitely the case in the context of generic algorithms where
certain expressions are required to be convertible to 'bool' but
not required to be 'bool'.
int main()
{
typedef char* CharPtr;

int* p = 0;
char* q1 = CharPtr( p );
char* q2 = static_cast<CharPtr>( p );
}

Don't know what you mean by "à la", but for q1 you have what various
compilers say is an OK reinterpret_cast, whereas for q2 you have what
the same compilers say is an invalid static_cast.

Yes, this is correct. I made a too strong generalization.
 
D

Dietmar Kuehl

But now you are mixing styles. Much better to use one or the other.

I consider it more important to fit certain expression on just one
line because it have trouble reading multi-line expressions. The
'static_cast said:
Otherwise you have to remember to use one when you can and the other
when you can't (or shouldn't) and this is messy. Better to use new
style even when C-Style is guaranteed to work as expected.

I have to remember to put in the conversion and not rely on the
operations to always return 'bool'. This is the hard part. The use
of an appropriate conversion is trivial and I manage to remember
the rule that it is safe to convert an expression
"convertible to 'bool'" explicitly to 'bool'. This doesn't take
much remembering for me.
Well, static_cast is easier to find.

Right. ... and multi-line expressions are harder to read. Since I
rarely search for the explicit conversions to 'bool' but frequently
read the code using them, I prefer to fit things on one line.
Also, bool(expr) could cast away constness unexpectedly just as C-Style
can. New style can't so again, not functionally equivelent.

'bool(expr)' yields an r-value as 'static_cast<bool>(expr)' does.
Also, which 'const' is exactly cast away or retain in either of
these expression...?
 

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

Members online

Forum statistics

Threads
473,795
Messages
2,569,644
Members
45,357
Latest member
RuthEsteve

Latest Threads

Top