GCC/MSVC++ difference

B

bleyddyn.apRhys

I have a bit of code that doesn't compile under MSVC++ but does under
GCC. Even under GCC, though, it seems odd that I don't need a std
namespace qualifier for the exp function.

Is this just one of those difference I have to #ifdef around, or is
there a bit of code that will compile under both?

Basically, I have a std::vector<double>. I want to replace each item
in the vector with the exp() of that item. The code does work, and
there's a simple work-around under Window's, but I'd prefer to
understand why it doesn't compile.

Below is the code and the VC++ error message. The workaround is to
replace exp with locExp in the call to transform.

Thanks for any suggestions!
Andrew


Version info:
Visual Studio 2005, Academic Edition, Version 8.0.50727.42
Visual C++ 2005 77633-233-0020534-41001

g++: powerpc-apple-darwin8-g++-4.0.1


Compiling...
transform.cpp
c:\documents and settings\asalamon\my documents\test
\transform.cpp(45) : error C2780: '_OutIt
std::transform(_InIt1,_InIt1,_InIt2,_OutIt,_Fn2)' : expects 5
arguments - 4 provided
c:\program files\microsoft visual studio 8\vc\include
\algorithm(797) : see declaration of 'std::transform'
c:\documents and settings\asalamon\my documents\test
\transform.cpp(45) : error C2914: 'std::transform' : cannot deduce
template argument as function argument is ambiguous
c:\documents and settings\asalamon\my documents\test
\transform.cpp(45) : error C2784: '_OutIt
std::transform(_InIt,_InIt,_OutIt,_Fn1)' : could not deduce template
argument for '_OutIt' from 'std::_Vector_iterator<_Ty,_Alloc>'
with
[
_Ty=double,
_Alloc=std::allocator<double>
]
c:\program files\microsoft visual studio 8\vc\include
\algorithm(682) : see declaration of 'std::transform'
Build log was saved at "file://c:\Documents and Settings\asalamon\My
Documents\Test\testTransform\testTransform\Debug\BuildLog.htm"
testTransform - 3 error(s), 0 warning(s)


// Begin code
#include <iomanip>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath> // for exp()

void testTransformExp();

int main()
{
testTransformExp();
}

void printVec( std::vector<double> &vec )
{
for( unsigned int i = 0; i < vec.size(); ++i )
std::cout << vec << ", ";
std::cout << std::endl;
}

inline double locExp( double val )
{
return exp(val);
}

void testTransformExp()
{
std::vector<double> res( 8, 0.0 );

res[0] = 1.0;
res[1] = 2.0;
res[2] = 10.0;
res[3] = 30.0;
res[4] = 100.0;
res[5] = 400.0;
res[6] = 1000.0;
res[7] = 5000.0;

std::transform( res.begin(), res.end(), res.begin(), exp ); //
calculate the exponent of each element
printVec( res );
}
 
I

Ian Collins

I have a bit of code that doesn't compile under MSVC++ but does under
GCC. Even under GCC, though, it seems odd that I don't need a std
namespace qualifier for the exp function.

std::transform( res.begin(), res.end(), res.begin(), exp );
printVec( res );
}
exp, having extern "C" linkage, probably doesn't match std::transform's
UnaryOperation template parameter.
 
P

P.J. Plauger

I have a bit of code that doesn't compile under MSVC++ but does under
GCC. Even under GCC, though, it seems odd that I don't need a std
namespace qualifier for the exp function.

Is this just one of those difference I have to #ifdef around, or is
there a bit of code that will compile under both?

Basically, I have a std::vector<double>. I want to replace each item
in the vector with the exp() of that item. The code does work, and
there's a simple work-around under Window's, but I'd prefer to
understand why it doesn't compile.

Below is the code and the VC++ error message. The workaround is to
replace exp with locExp in the call to transform.

Right. The problem you face is that VC++ conforms better to the C++
Standard than does GCC. The former provides the required overloads
for exp; the latter is at the mercy of the underlying C library to
provide those overloads, and certainly glibc fails to do so. By
interposing the wrapper function, you disambiguate the call to
transform.

HTH,

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
B

bleyddyn.apRhys

Right. The problem you face is that VC++ conforms better to the C++
Standard than does GCC. The former provides the required overloads
for exp; the latter is at the mercy of the underlying C library to
provide those overloads, and certainly glibc fails to do so. By
interposing the wrapper function, you disambiguate the call to
transform.

HTH,

P.J. Plauger
Dinkumware, Ltd.http://www.dinkumware.com

I'm not sure if it helps my understanding much, but thanks! Looking
through the cmath header file, it certainly seems like there are
overloads for exp, but that's why I didn't understand why I don't need
a std:: qualifier for exp. Maybe the __enable_if... macro prevents any
re-definition of exp?

<snipped from parts of cmath>
#undef exp
....
namespace std
{
using ::exp;

inline float
exp(float __x)
{ return __builtin_expf(__x); }

inline long double
exp(long double __x)
{ return __builtin_expl(__x); }

template<typename _Tp>
inline typename __enable_if<double,
__is_integer<_Tp>::__value>::__type
exp(_Tp __x)
{ return __builtin_exp(__x); }
}

I did come up with what seems like a cleaner way to fix it, though:

typedef double (*expType) (double);
std::transform( res.begin(), res.end(), res.begin(),
static_cast<expType>(exp) );

It builds and runs properly under both compilers. I guess I'll just
leave it at that for now, since it does seem to work.

Thanks!
Andrew
 
H

Howard Hinnant

I'm not sure if it helps my understanding much, but thanks! Looking
through the cmath header file, it certainly seems like there are
overloads for exp, but that's why I didn't understand why I don't need
a std:: qualifier for exp. Maybe the __enable_if... macro prevents any
re-definition of exp?

<snipped from parts of cmath>
#undef exp
...
namespace std
{
using ::exp;

inline float
exp(float __x)
{ return __builtin_expf(__x); }

inline long double
exp(long double __x)
{ return __builtin_expl(__x); }

template<typename _Tp>
inline typename __enable_if<double,
__is_integer<_Tp>::__value>::__type
exp(_Tp __x)
{ return __builtin_exp(__x); }
}

I did come up with what seems like a cleaner way to fix it, though:

typedef double (*expType) (double);
std::transform( res.begin(), res.end(), res.begin(),
static_cast<expType>(exp) );

It builds and runs properly under both compilers. I guess I'll just
leave it at that for now, since it does seem to work.

What happens if you use std::exp instead of exp. Technically that is
all that should be exposed by <cmath> today.

-Howard
 
B

bleyddyn.apRhys

What happens if you use std::exp instead of exp. Technically that is
all that should be exposed by <cmath> today.

-Howard

With this line:
std::transform( res.begin(), res.end(), res.begin(), std::exp );

For gcc:
transform.cpp: In function 'void testTransformExp()':
transform.cpp:46: error: no matching function for call to
'transform(__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*,
std::vector<double, std::allocator<double> > >,
__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >, <unknown type>)'

And a similar error from VC++ (sorry, can't copy/paste from Windows):
error C2780 ... expects 5 arguments - 4 provided
.... can't deduce template argument as function argument is ambiguous
....
 
K

Kai-Uwe Bux

I have a bit of code that doesn't compile under MSVC++ but does under
GCC. Even under GCC, though, it seems odd that I don't need a std
namespace qualifier for the exp function.

Is this just one of those difference I have to #ifdef around, or is
there a bit of code that will compile under both?

Basically, I have a std::vector<double>. I want to replace each item
in the vector with the exp() of that item. The code does work, and
there's a simple work-around under Window's, but I'd prefer to
understand why it doesn't compile.

Below is the code and the VC++ error message. The workaround is to
replace exp with locExp in the call to transform.

Thanks for any suggestions!
Andrew
[snip]
// Begin code
#include <iomanip>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cmath> // for exp()

void testTransformExp();

int main()
{
testTransformExp();
}

void printVec( std::vector<double> &vec )
{
for( unsigned int i = 0; i < vec.size(); ++i )
std::cout << vec << ", ";
std::cout << std::endl;
}

inline double locExp( double val )
{
return exp(val);
}

void testTransformExp()
{
std::vector<double> res( 8, 0.0 );

res[0] = 1.0;
res[1] = 2.0;
res[2] = 10.0;
res[3] = 30.0;
res[4] = 100.0;
res[5] = 400.0;
res[6] = 1000.0;
res[7] = 5000.0;

std::transform( res.begin(), res.end(), res.begin(), exp );


I think, the compiler needs some help to chose the right overload for
std::exp:

std::transform( res.begin(), res.end(), res.begin(),
static_cast< double(*)(double)> ( std::exp ) );

[snip]
printVec( res );
}


Best

Kai-Uwe Bux
 

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

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top