why do I need ::sin, not std::sin?

  • Thread starter Alexander Stippler
  • Start date
A

Alexander Stippler

Hi,

simple question. Why does this not work:

#include <algorithm>
#include <cmath>
#include <iostream>

int
main()
{
double a[2];
a[0] = 0;a[1] = M_PI/2.;
std::transform(a, a+2, a, std::sin);
std::cout << a[0] << ", " << a[1] << std::endl;
return 0;
}

for gcc and icc the type of the third argument of transform is unknown. If I
use the global ::sin it works fine. Why? I include cmath and there sin is
defined in namespace std, so why is it unknown?

regards,
alex
 
R

red floyd

Alexander said:
Hi,

simple question. Why does this not work:

#include <algorithm>
#include <cmath>
#include <iostream>

int
main()
{
double a[2];
a[0] = 0;a[1] = M_PI/2.;
std::transform(a, a+2, a, std::sin);
std::cout << a[0] << ", " << a[1] << std::endl;
return 0;
}

for gcc and icc the type of the third argument of transform is unknown. If I
use the global ::sin it works fine. Why? I include cmath and there sin is
defined in namespace std, so why is it unknown?

regards,
alex

IANAG (I am not a guru), and am probably way off base (please correct me
guys -- please no flames).

Isn't std::sin a template? Would you need to specifically instantiate
std::sin, i.e.

std::transform(a, a+2, a, std::sin<double>)

You might also want to use std::ptr_fun as a wrapper to std::sin (or ::sin).
 
R

Rob Williscroft

Alexander Stippler wrote in in
comp.lang.c++:
Hi,

simple question. Why does this not work:

#include <algorithm>
#include <cmath>
#include <iostream>

int
main()
{
double a[2];
a[0] = 0;a[1] = M_PI/2.;
std::transform(a, a+2, a, std::sin);
std::cout << a[0] << ", " << a[1] << std::endl;
return 0;
}

for gcc and icc the type of the third argument of transform is
unknown. If I use the global ::sin it works fine. Why? I include cmath
and there sin is defined in namespace std, so why is it unknown?

regards,
alex

There are several overloads of std::sin, you need to pick one:

std::transform(a, a+2, a, (double (*)(double)std::sin);

Note M_PI isn't AFAICT Standard C++, you can use:

double const M_PI = (2.0 * std::acos( 0.0 ));

Though maybe:

double const double_pi = (2.0 * std::acos( 0.0 ));

Whould be better.

HTH.

Rob.
 
P

Pete Becker

red said:
Isn't std::sin a template?

No, just an ordinary function, with overloads for arguments of type
float, double, and long double. (There's also a sin template for
arguments of type complex<T>, but that's not involved here)
 
A

Alexander Stippler

red said:
Alexander said:
Hi,

simple question. Why does this not work:

#include <algorithm>
#include <cmath>
#include <iostream>

int
main()
{
double a[2];
a[0] = 0;a[1] = M_PI/2.;
std::transform(a, a+2, a, std::sin);
std::cout << a[0] << ", " << a[1] << std::endl;
return 0;
}

for gcc and icc the type of the third argument of transform is unknown.
If I use the global ::sin it works fine. Why? I include cmath and there
sin is defined in namespace std, so why is it unknown?

regards,
alex

IANAG (I am not a guru), and am probably way off base (please correct me
guys -- please no flames).

Isn't std::sin a template? Would you need to specifically instantiate
std::sin, i.e.

std::transform(a, a+2, a, std::sin<double>)

You might also want to use std::ptr_fun as a wrapper to std::sin (or


std::transform(a, a+2, a, std::sin<double>)

What about this line if you have <complex> included? I took a look at the
<cmath> source code. It defines (in namespace std!) sin for float argument
as non template function, but the example above results in the same error
for float. I'm confused.

regards,
alex
 
V

Victor Bazarov

Rob said:
Alexander Stippler wrote in in
comp.lang.c++:

Hi,

simple question. Why does this not work:

#include <algorithm>
#include <cmath>
#include <iostream>

int
main()
{
double a[2];
a[0] = 0;a[1] = M_PI/2.;
std::transform(a, a+2, a, std::sin);
std::cout << a[0] << ", " << a[1] << std::endl;
return 0;
}

for gcc and icc the type of the third argument of transform is
unknown. If I use the global ::sin it works fine. Why? I include cmath
and there sin is defined in namespace std, so why is it unknown?

regards,
alex


There are several overloads of std::sin, you need to pick one:

std::transform(a, a+2, a, (double (*)(double)std::sin);

Unmatched parentheses. Did you mean to write

std::transform(a, a+2, a, (double (*)(double))std::sin);

(i.e. use the C-style cast)?

BTW, why can't it figure out the type of 'std::sin'? Is that because
it's overloaded?

V
 
P

Pete Becker

Rob said:
Note M_PI isn't AFAICT Standard C++, you can use:

double const M_PI = (2.0 * std::acos( 0.0 ));

Though maybe:

double const double_pi = (2.0 * std::acos( 0.0 ));

Whould be better.

The latter, definitely. Otherwise you end up calling acos every time you
use the value of M_PI.
 
V

Victor Bazarov

Pete said:
The latter, definitely. Otherwise you end up calling acos every time you
use the value of M_PI.

Huh? I must be missing something. Did you mean to support the usual
const versus macro argument but instead implied that if the name of the
constant is M_PI, then it's somehow a function call instead of a const,
and if the name is 'double_pi', then it's reverse?

Rob didn't try to suggest

#define M_PI (2.0 * std::acos(0))

, did he? So, the latter or the former should be basically the same.

Victor
 
R

Rob Williscroft

Victor Bazarov wrote in in comp.lang.c++:
Unmatched parentheses. Did you mean to write

std::transform(a, a+2, a, (double (*)(double))std::sin);

Thanks, I should have "cut-n-paste" from my editor.
(i.e. use the C-style cast)?

BTW, why can't it figure out the type of 'std::sin'? Is that because
it's overloaded?

Yes, but its also because std::transform's signature doesn't do
anything to help:

template<class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator
transform(
InputIterator first, InputIterator last,
OutputIterator result, UnaryOperation op
)
;

I.e. UnaryOperation is independant of InputIterator and OutputIterator.

Deducable example:

#include <cmath>

template < typename T >
T f( T arg, T (*func)( T ) )
{
return func( arg );
}

int main()
{
f( 0.0, std::sin );
}


Rob.
 
V

Victor Bazarov

red said:
Alexander said:
Hi,

simple question. Why does this not work:

#include <algorithm>
#include <cmath>
#include <iostream>

int
main()
{
double a[2];
a[0] = 0;a[1] = M_PI/2.;

No such thing as 'M_PI' in the standard C++, BTW.
std::transform(a, a+2, a, std::sin);
std::cout << a[0] << ", " << a[1] << std::endl;
return 0;
}

for gcc and icc the type of the third argument of transform is
unknown. If I
use the global ::sin it works fine. Why? I include cmath and there sin is
defined in namespace std, so why is it unknown?

regards,
alex

IANAG (I am not a guru), and am probably way off base (please correct me
guys -- please no flames).

Isn't std::sin a template?

yes. For said:
Would you need to specifically instantiate
std::sin, i.e.

std::transform(a, a+2, a, std::sin<double>)
No.


You might also want to use std::ptr_fun as a wrapper to std::sin (or
::sin).

That might help. I am not sure I understand why, though.

For all I can see in the Standard, the 'std::transform' template has
to be able to figure out the type of 'std::sin'. It's an overloaded
function and the lookup should be limited to the type of the first
argument.

I would like to really hear from Greg Comeau on this, too. His online
try-it-out thing refuses to compile and I cannot figure out how to make
it.

Victor
 
V

Victor Bazarov

Rob said:
Victor Bazarov wrote in in comp.lang.c++:




Thanks, I should have "cut-n-paste" from my editor.




Yes, but its also because std::transform's signature doesn't do
anything to help:

template<class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator
transform(
InputIterator first, InputIterator last,
OutputIterator result, UnaryOperation op
)
;

I.e. UnaryOperation is independant of InputIterator and OutputIterator.

Ah... That would explain it.
Deducable example:

#include <cmath>

template < typename T >
T f( T arg, T (*func)( T ) )
{
return func( arg );
}

Yes, that makes 'func' dependent on T. std::transform can't do that
because it would unnecessarily limit it to the use of functions only
and we don't want that. And there is no real way to define in the
template argument list "something that has operator() defined for it
which takes certain arguments and returns a certain value". Too bad.
int main()
{
f( 0.0, std::sin );
}


Rob.

Thanks, Rob.

V
 
R

Rob Williscroft

Pete Becker wrote in in comp.lang.c++:
The latter, definitely. Otherwise you end up calling acos every time you
use the value of M_PI.

You possibly though I wrote:

#define M_PI (2.0 * std::acos( 0.0 ))

Which I'll admit I did think about writing :), though not for very long.


Rob.
 
R

red floyd

red said:
Alexander Stippler wrote:

[redacted]

Thanks for the corrections guys. I didn't have my copy of Josuttis handy.

I still think that using ptr_fun might disambiguate, i.e.

std::transform(a, a+2, a, std::ptr_fun<double,double>(std::sin));
 
P

Pete Becker

Victor said:
Rob didn't try to suggest

#define M_PI (2.0 * std::acos(0))

, did he? So, the latter or the former should be basically the same.

I didn't read his message closely enough, and assumed it was still a
macro.
 
P

Pete Becker

Rob said:
You possibly though I wrote:

#define M_PI (2.0 * std::acos( 0.0 ))

Which I'll admit I did think about writing :), though not for very long.

Yup. Sorry.
 

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

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top