473,387 Members | 1,834 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

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 9023
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: qazmlp | last post by:
I was using the following code to convert the string to lowercase. string foo = "Some Mixed Case Text"; transform(foo.begin(), foo.end(), foo.begin(), tolower); I thought the above code is...
20
by: Steffen Brinkmann | last post by:
Hi! I tried to modify the transform algorithm in a way that it doesn't take iterators, but a reference to a container class and a value, because Mostly I need to do an operation of a container...
11
by: TheDD | last post by:
Hello, i don't manage to use the tolower() function: #include <algorithm> #include <iostream> #include <locale> #include <string> using std::cout;
14
by: Alexander Stippler | last post by:
Hi, simple question. Why does this not work: #include <algorithm> #include <cmath> #include <iostream> int main()
4
by: Steven T. Hatton | last post by:
This code works for dividing each element of a boost::array<> by a value of its element type: template <typename T, size_t S> inline boost::array<T, S>& operator/=( boost::array<T, S>& lhs,...
2
by: Alex | last post by:
I don't know why this works: class C { public: C(int x, int y) : a(x), b(y) {} int a,b; }; float avg(const C* c) {
4
by: Ney André de Mello Zunino | last post by:
Hello. The following program: #include <list> #include <iterator> #include <algorithm> #include <cmath> #include <iostream>
6
by: Vijai Kalyan | last post by:
Hello, I am trying to use std::transform to take in a collection of strings, transform them and insert the result into an output container. So, I wrote something like this: std::wstring...
2
by: kvnil | last post by:
Cheers, I've been struggling all day today with this, maybe you could give me some useful pointers. I would like to (elegantly) concatenate a string out of all node values in a map. I have to...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.