By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,194 Members | 889 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,194 IT Pros & Developers. It's quick & easy.

std::transform ugly cast

P: n/a

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
Share this Question
Share on Google+
8 Replies


P: n/a
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

P: n/a
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

P: n/a
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

P: n/a

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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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.