473,498 Members | 1,815 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Standard math functions as operations in std::transform calls

Hello.

The following program:

#include <list>
#include <iterator>
#include <algorithm>
#include <cmath>
#include <iostream>

int main()
{
using namespace std;

float elem[] = { 4, 7, 2, 8, 12 };
list<floatval(elem, elem + sizeof elem / sizeof elem[0]);

cout << "ORIGINAL\n\t";
copy(val.begin(), val.end(), ostream_iterator<float>(cout, "\n\t"));

transform(val.begin(), val.end(), val.begin(), log);

cout << "\nTRANSFORMED\n\t";
copy(val.begin(), val.end(), ostream_iterator<float>(cout, "\n\t"));

cout << '\n';
}

fails to compile in g++ 4.0, giving the following error message:

tran.cpp: In function `int main()':
tran.cpp:17: no matching function for call to `transform(
std::_List_iterator<float, float&, float*>, std::_List_iterator<float,
float&, float*>, std::_List_iterator<float, float&, float*>, <unknown
type>
)'

"Unknown type"?! I wondered why the compiler was not being able to
deduce it. Nothing occurred to me except the fact that the std::log
function (as most other math functions) has a handful of overloaded
versions. Could that be causing the compiler to get confused?

I then decided to try the same code in VC++ 8.00 on Windows. The program
compiles and produces the following expected results:

ORIGINAL
4
7
2
8
12

TRANSFORMED
1.38629
1.94591
0.693147
2.07944
2.48491

I would appreciate if anyone could let me know whether that program is
valid.

Thank you,

--
Ney André de Mello Zunino
Jul 27 '06 #1
4 3326
Ney André de Mello Zunino wrote:
...
fails to compile in g++ 4.0, giving the following error message:

tran.cpp: In function `int main()':
tran.cpp:17: no matching function for call to `transform(
std::_List_iterator<float, float&, float*>, std::_List_iterator<float,
float&, float*>, std::_List_iterator<float, float&, float*>, <unknown
type>
)'

"Unknown type"?! I wondered why the compiler was not being able to
deduce it. Nothing occurred to me except the fact that the std::log
function (as most other math functions) has a handful of overloaded
versions. Could that be causing the compiler to get confused?
Yes, exactly.

To make it work you have to choose one specific overloaded version of 'log'
manually:

transform(val.begin(), val.end(), val.begin(), (float (*)(float)) log);
I then decided to try the same code in VC++ 8.00 on Windows. The program
compiles and produces the following expected results:
...
The older version of VC++ are known to suppress the overloaded versions of match
functions (unless it is explicitly requested by [un]defining some MS-specific
macro). That could be the case with you compiler as well, which is what makes
the code to compile (just a guess).

--
Best regards,
Andrey Tarasevich
Jul 27 '06 #2

Ney André de Mello Zunino wrote:
Hello.

The following program:

#include <list>
#include <iterator>
#include <algorithm>
#include <cmath>
#include <iostream>

int main()
{
using namespace std;

float elem[] = { 4, 7, 2, 8, 12 };
list<floatval(elem, elem + sizeof elem / sizeof elem[0]);

cout << "ORIGINAL\n\t";
copy(val.begin(), val.end(), ostream_iterator<float>(cout, "\n\t"));

transform(val.begin(), val.end(), val.begin(), log);

cout << "\nTRANSFORMED\n\t";
copy(val.begin(), val.end(), ostream_iterator<float>(cout, "\n\t"));

cout << '\n';
}

fails to compile in g++ 4.0, giving the following error message:

tran.cpp: In function `int main()':
tran.cpp:17: no matching function for call to `transform(
std::_List_iterator<float, float&, float*>, std::_List_iterator<float,
float&, float*>, std::_List_iterator<float, float&, float*>, <unknown
type>
)'

"Unknown type"?! I wondered why the compiler was not being able to
deduce it. Nothing occurred to me except the fact that the std::log
function (as most other math functions) has a handful of overloaded
versions. Could that be causing the compiler to get confused?

I then decided to try the same code in VC++ 8.00 on Windows. The program
compiles and produces the following expected results:

ORIGINAL
4
7
2
8
12

TRANSFORMED
1.38629
1.94591
0.693147
2.07944
2.48491

I would appreciate if anyone could let me know whether that program is
valid.

Thank you,

--
Ney André de Mello Zunino
Isnt it because of the linkage issue ? Vandervoorde's book describes
about why you need either to typecast or provde an intermediate adapter.

Jul 27 '06 #3
Andrey Tarasevich wrote:
Ney André de Mello Zunino wrote:
[snip]
>"Unknown type"?! I wondered why the compiler was not being able to
deduce it. Nothing occurred to me except the fact that the std::log
function (as most other math functions) has a handful of overloaded
versions. Could that be causing the compiler to get confused?

Yes, exactly.

To make it work you have to choose one specific overloaded version of 'log'
manually:

transform(val.begin(), val.end(), val.begin(), (float (*)(float)) log);
I had thought that the compiler might be able to figure out which
overloaded version of the function to call because it could tell the
type of the argument passed to it (inside std::transform) at compile
time. But that's probably not such an easy task.

The pointer-to-function cast doesn't look pretty, but I guess my code
had better include it if I want it to be portable.

[snip]

Regards,

--
Ney André de Mello Zunino
Graduando em Ciência da Computação
Universidade Federal de Santa Catarina
Jul 27 '06 #4
Ney André de Mello Zunino wrote:
...
>>"Unknown type"?! I wondered why the compiler was not being able to
deduce it. Nothing occurred to me except the fact that the std::log
function (as most other math functions) has a handful of overloaded
versions. Could that be causing the compiler to get confused?

Yes, exactly.

To make it work you have to choose one specific overloaded version of 'log'
manually:

transform(val.begin(), val.end(), val.begin(), (float (*)(float)) log);

I had thought that the compiler might be able to figure out which
overloaded version of the function to call because it could tell the
type of the argument passed to it (inside std::transform) at compile
time. But that's probably not such an easy task.
...
Unfortunately, in order to obtain a meaningful body for 'std::transform' (i.e.
specialize it) the compiler has to know all template arguments. And functor type
is one of them, meaning that it has to be supplied in advance. Moreover,
apparently the template interface of 'std::transform' is not supposed to require
that functor's parameter type (and return type) is identical to the iterators'
value type. In some case, for example, you might want to apply, say, 'int
abs(int)' to a vector of 'float's in order to perform truncation and take the
absolute value at the same time.

However, there's still a generic technique that enables the "postponed" overload
resolution in cases like this, but it is based on using a functor of class type,
not a regular function pointer. If we define a class like this

struct Log {
template<typename TT operator()(T v) { return log(v); }
};

and pass an object of this class to 'std::transform'

transform(val.begin(), val.end(), val.begin(), Log());

the appropriate version of 'log' will indeed be generated and called
automatically based on the actual argument type.

--
Best regards,
Andrey Tarasevich
Jul 28 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
31854
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
3809
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...
3
2933
by: claude uq | last post by:
Hello, Am trying to use template functions within some class to convert int, float, doubles, etc into strings. Below, three ways to do it via use of "to_string(const T & Value)" . The only...
1
2233
by: Brian McGuinness | last post by:
I have a question about using the STL transform algorithm in a function. What I want to do is define a group of array classes to represent APL-style arrays (arrays in which the number of...
4
3643
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,...
8
9029
by: Dilip | last post by:
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...
6
4935
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
2706
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...
19
3221
by: Taras_96 | last post by:
Hi all, A poster at http://bytes.com/forum/thread60652.html implies that using strtoupper in transform doesn't work because ctype.h may define strtoupper as a macro: "The problem is that most...
0
7126
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
7168
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
7210
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...
0
7381
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5465
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4916
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3087
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
659
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
293
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.