468,771 Members | 1,929 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,771 developers. It's quick & easy.

std::transform ugly cast


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(*)

Jun 27 '06 #1
8 8771
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

--

Frederick Gotham
Jun 27 '06 #2
Dilip wrote:
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(),
dest.begin(), addvalue<int, 5>);
}
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 27 '06 #3
Dilip wrote:
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.

--
Best regards,
Andrey Tarasevich
Jun 27 '06 #4

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

Just a quick point..

Victor Bazarov wrote:
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!

Jun 27 '06 #5
G'day,

Dilip wrote:
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));

--
Cheers,
Gryff

Jun 27 '06 #6
Dilip wrote:
[..] 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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 28 '06 #7
Victor Bazarov wrote:
Dilip wrote:
[..] 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/wg...fects.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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 28 '06 #8
Gryff Stokoe wrote:
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.

Jun 28 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by qazmlp | last post: by
20 posts views Thread by Steffen Brinkmann | last post: by
11 posts views Thread by TheDD | last post: by
14 posts views Thread by Alexander Stippler | last post: by
4 posts views Thread by Steven T. Hatton | last post: by
2 posts views Thread by Alex | last post: by
4 posts views Thread by Ney André de Mello Zunino | last post: by
6 posts views Thread by Vijai Kalyan | last post: by
2 posts views Thread by kvnil | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.