std::transform ugly cast

D

Dilip

I was reading the C++ templates (Josuttis et al) book and came across
an example that left me scratching my head.. there is a function
template:

template<typename T, int val>
T addvalue(T const& x)
{
return x + val;
}

that is used in transform like so:

std::transform(source.begin(), source.end(), dest.begin(),
addvalue<int, 5>);

the author goes on to say that because of some function template
overload issues we actually need to cast the last parameter like this:

(int(*)(int const&)) addvalue<int, 5>

can someone please enlighten me? why is the cast needed? i also don't
understand (embarassingly) what it means to say int(*)
 
F

Frederick Gotham

Dilip posted:

template<typename T, int val>
T addvalue(T const& x)
{
return x + val;
}

that is used in transform like so:

std::transform(source.begin(), source.end(), dest.begin(),
addvalue<int, 5>);

the author goes on to say that because of some function template
overload issues we actually need to cast the last parameter like this:

(int(*)(int const&)) addvalue<int, 5>


You're casting from:

int (*)(const int &)

To:

int (*)(const int &)


Seems like a redundant cast to me... but I'd have to see all of the code.

I also don't understand (embarassingly) what it means to say int(*)


No need for embarassment -- we all have to learn these things at some
stage.


An array of pointers: int *array[64];
A pointer to an array: int (*array)[64];

A function which returns a pointer: int *Func(double);
A pointer to a function: int (*Func)(double);


It's all to do with operator precedence:

http://www.difranco.net/cop2334/cpp_op_prec.htm
 
V

Victor Bazarov

Dilip said:
I was reading the C++ templates (Josuttis et al) book and came across
an example that left me scratching my head.. there is a function
template:

template<typename T, int val>
T addvalue(T const& x)
{
return x + val;
}

that is used in transform like so:

std::transform(source.begin(), source.end(), dest.begin(),
addvalue<int, 5>);

the author goes on to say that because of some function template
overload issues we actually need to cast the last parameter like this:

(int(*)(int const&)) addvalue<int, 5>

can someone please enlighten me? why is the cast needed?

I don't think it is needed. Have you tried without it? Do you get any
compiler error message?

#include <algorithm>
#include <vector>

template<typename T, int val>
T addvalue(T const& x)
{
return x + val;
}

int main() {
std::vector<int> source, dest;
// that is used in transform like so:
std::transform(source.begin(), source.end(),
i also
don't understand (embarassingly) what it means to say int(*)

int(*)(...)

Is a nameless declaration meaning "a pointer to a function that takes
.... arguments and returns an int.

Just for using a C-style cast and insisting on its necessity the
author should join Schildt in exile!

V
 
A

Andrey Tarasevich

Dilip said:
I was reading the C++ templates (Josuttis et al) book and came across
an example that left me scratching my head.. there is a function
template:

template<typename T, int val>
T addvalue(T const& x)
{
return x + val;
}

that is used in transform like so:

std::transform(source.begin(), source.end(), dest.begin(),
addvalue<int, 5>);

the author goes on to say that because of some function template
overload issues we actually need to cast the last parameter like this:

(int(*)(int const&)) addvalue<int, 5>

can someone please enlighten me? why is the cast needed?

Hmm... I don't really see why the cast might be needed. I'd say it
isn't. Are you sure it wasn't mentioned as a mere quirk of some
particular compiler in the book? I tried two different ones and both
quietly accepted the code without the cast.
i also don't
understand (embarassingly) what it means to say int(*)

To say 'int(*)' means nothing. However, 'int(*)()', for example, would
designate a type - "pointer to function that takes no parameters and
returns an int". A declaration of an object of that type would look as
follows

int (*ptr)();

and if you take out the 'ptr' you'll be left with type designator, i.e.
something that can be used in casts.
 
D

Dilip

Thanks Fredrick and Victor. Sometimes this list is much more
informative and responsive than c.l.c++.m!

Just a quick point..

Victor said:
I don't think it is needed. Have you tried without it? Do you get any
compiler error message?

Sorry Victor -- I didn't try it. I just assumed I would get compiler
errors. I didn't dare question Josuttis/Vandevoorde :)
Just for using a C-style cast and insisting on its necessity the
author should join Schildt in exile!

Good one! ROTFL!
 
G

Gryff Stokoe

G'day,
I was reading the C++ templates (Josuttis et al) book and came across
an example that left me scratching my head.. there is a function
template:

template<typename T, int val>
T addvalue(T const& x)
{
return x + val;
}

that is used in transform like so:

std::transform(source.begin(), source.end(), dest.begin(),
addvalue<int, 5>);

the author goes on to say that because of some function template
overload issues we actually need to cast the last parameter like this:

(int(*)(int const&)) addvalue<int, 5>

can someone please enlighten me? why is the cast needed? i also don't
understand (embarassingly) what it means to say int(*)

I doubt the cast is actually needed in this example. However, it is used
to disambiguate overloaded functions passed as the functor argument to
std::transform. For example, to lowercase a string we might use

std::string s = "HeLlO";
std::transform(s.begin(), s.end(), s.begin(), std::tolower);

However, std::tolower is overloaded and the compile will fail because of
the ambiguity. We specify which one we want through an explicit cast

std::transform(s.begin(), s.end(), s.begin(),
static_cast<int(*)(int)>(std::tolower));
 
V

Victor Bazarov

Dilip said:
[..] I just assumed I would get compiler
errors. I didn't dare question Josuttis/Vandevoorde :)

Are you saying that you found it in "C++ Templates"? What page?
What edition?

V
 
V

Victor Bazarov

Victor said:
Dilip said:
[..] I just assumed I would get compiler
errors. I didn't dare question Josuttis/Vandevoorde :)

Are you saying that you found it in "C++ Templates"? What page?
What edition?

OK, I found the place myself. The authors talk about the Issue 115
which has been identified as a defect in the Standard and the proposed
resolution is a simple change in wording, already allowing omitting
the cast. See
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#115

It is possible that my limited understanding of function lookup has
affected my judgement as to whether it should be currently implemented
as it is, but the reality is that as you've seen, many implementations
already do as we'd expect and not as the Standard would seem to dictate
(at least according to Josuttis).

V
 
D

Dilip

Gryff said:
I doubt the cast is actually needed in this example. However, it is used
to disambiguate overloaded functions passed as the functor argument to
std::transform. For example, to lowercase a string we might use

Gotcha! This is what I was missing. The book did state that even if
the set of overloaded candidate functions is only _one_, the cast still
has to be provided. Victor unearthed a defect report (that is also
mentioned in that book). The only mistake is I didn't really try the
code before posting here.
 

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

No members online now.

Forum statistics

Threads
474,201
Messages
2,571,048
Members
47,647
Latest member
NelleMacy9

Latest Threads

Top