Trouble with std::transform using g++ but Ok with VS 2010 Express

This program works gives expected results using VS 2010 Express, but does not compile using g++ (GCC) 4.8.2. The first three versions of convertComplexToFloat() work the same on both platforms. It's just convertComplexToFloat4() that is producing problems.
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
using namespace std;

typedef complex<float> Complex_f;
typedef valarray<Complex_f> VCF_t;
typedef valarray<float> VF_t;

gslice gslice2DSet(size_t start, size_t dim1, size_t dim2, size_t stride1, size_t stride2)
{
   size_t lengths[]= {dim1,    dim2};
   size_t strides[]= {stride1, stride2};

   gslice gs (
      start,
      valarray<size_t>(lengths,2),
      valarray<size_t>(strides,2));

   return gs;
}

template<class T>
void print2d(valarray<T> &v, size_t nRow, size_t nCol) {
   for(size_t r = 0; r < nRow; ++r)
   {
      for(size_t c = 0; c < nCol; ++c)
      {
         cout << ' ' << v[r*nCol + c];
      }
      cout << endl;
   }
   cout << endl;
}

template<class T>
void foo(valarray<T>& vala, gslice& gs)
{
   size_t nRows = gs.size()[0];
   size_t nCols = gs.size()[1];
   valarray<T> varesult = vala[gs];
   print2d(varesult, nRows, nCols);
}

float Norm(Complex_f cf)
{
   return cf.real() * cf.real() + cf.imag() * cf.imag();
}

void convertComplexToFloat1(VCF_t& vac, VF_t& vaf)
{
   for(size_t i=0; i<vac.size(); ++i)
   {
      vaf[i] = Norm(vac[i]);
   }
}

void convertComplexToFloat2(VCF_t& vac, VF_t& vaf)
{
   std::transform(&vac[0], &vac[vac.size()], &vaf[0], Norm);
}

void convertComplexToFloat3(VCF_t &vac, VF_t &vaf)
{
   std::transform(&vac[0], &vac[vac.size()], &vaf[0], norm<float>);
}

void convertComplexToFloat4(VCF_t &vac, VF_t &vaf)
{
   VCF_t normVac = vac * vac.apply(conj<float>);
   std::transform(&normVac[0], &normVac[vac.size()], &vaf[0], real<float>);
}

int main()
{
   const int M=5, N=7;
   const Complex_f vacFill(3.0, 4.0);
   VCF_t vac(vacFill, M*N);

   gslice gsOrig = gslice2DSet(0, M,N, N,1);
   gslice gs = gslice2DSet(8, 3,4, N,1);
   vac[gs] = Complex_f(30,40);

   foo(vac, gsOrig);
   foo(vac, gs);

   VF_t vaf(M*N);
   gs = gslice2DSet(9, 3,4, N,1);
   foo(vac, gs);

   vaf = 1.0;
cout << "v.1" << endl;
   convertComplexToFloat1(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.2" << endl;
   convertComplexToFloat2(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.3" << endl;
   convertComplexToFloat3(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.4" << endl;
   convertComplexToFloat4(vac, vaf);
   foo(vaf, gsOrig);

}

Open in new window

VS 2010 gives this output:
 (3,4) (3,4) (3,4) (3,4) (3,4) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (3,4) (3,4) (3,4) (3,4) (3,4) (3,4)

 (30,40) (30,40) (30,40) (30,40)
 (30,40) (30,40) (30,40) (30,40)
 (30,40) (30,40) (30,40) (30,40)

 (30,40) (30,40) (30,40) (3,4)
 (30,40) (30,40) (30,40) (3,4)
 (30,40) (30,40) (30,40) (3,4)

v.1
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.2
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.3
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.4
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

Open in new window

But g++ gives the following errors:
$ g++ -Wall complexToFloat.cpp && ./a.exe
complexToFloat.cpp: In function ‘void convertComplexToFloat4(VCF_t&, VF_t&)’:
complexToFloat.cpp:72:74: error: no matching function for call to ‘transform(std::complex<float>*, std::complex<float>*, float*, <unresolved overloaded function type>)’
    std::transform(&normVac[0], &normVac[vac.size()], &vaf[0], real<float>);
                                                                          ^
complexToFloat.cpp:72:74: note: candidates are:
In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/algorithm:62:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/valarray:38,
                 from complexToFloat.cpp:2:
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:4915:5: note: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
     transform(_InputIterator __first, _InputIterator __last,
     ^
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:4915:5: note:   template argument deduction/substitution failed:
complexToFloat.cpp:72:74: note:   could not resolve address from overloaded function ‘real<float>’
    std::transform(&normVac[0], &normVac[vac.size()], &vaf[0], real<float>);
                                                                          ^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/algorithm:62:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/valarray:38,
                 from complexToFloat.cpp:2:
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:4952:5: note: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
     transform(_InputIterator1 __first1, _InputIterator1 __last1,
     ^
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/bits/stl_algo.h:4952:5: note:   template argument deduction/substitution failed:
complexToFloat.cpp:72:74: note:   could not resolve address from overloaded function ‘real<float>’
    std::transform(&normVac[0], &normVac[vac.size()], &vaf[0], real<float>);

Open in new window

The VS 2010 Express command line is:
/ZI /nologo /W4 /WX- /Od /Oy- /D "_MBCS" /D "_SCL_SECURE_NO_WARNINGS" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Debug\ComplexToFloat.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue 

Open in new window

Using g++, what change do I make to get the program to work? I believe the problem lies with the complex function real which probably does not require the <float> to help disambiguate the templated function. But without it, VS 2010 gives an error that would be consistent with a binary op rather than a unary op.
complextofloat.cpp(72): error C2780: '_OutTy *std::transform(_InIt1,_InIt1,_InTy (&)[_InSize],_OutTy (&)[_OutSize],_Fn2)' : expects 5 arguments - 4 provided

Open in new window


Also, is it possible to write convertComplexToFloat4() so that it compiles/runs correctly on both platforms?
LVL 33
phoffric\Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

evilrixSenior Software Engineer (Avast)Commented:
Your functors are wrong. They need to take type Complex_f and return type float.

#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
using namespace std;

typedef complex<float> Complex_f;
typedef valarray<Complex_f> VCF_t;
typedef valarray<float> VF_t;

gslice gslice2DSet(size_t start, size_t dim1, size_t dim2, size_t stride1, size_t stride2)
{
   size_t lengths[]= {dim1,    dim2};
   size_t strides[]= {stride1, stride2};

   gslice gs (
      start,
      valarray<size_t>(lengths,2),
      valarray<size_t>(strides,2));

   return gs;
}

template<class T>
void print2d(valarray<T> &v, size_t nRow, size_t nCol) {
   for(size_t r = 0; r < nRow; ++r)
   {
      for(size_t c = 0; c < nCol; ++c)
      {
         cout << ' ' << v[r*nCol + c];
      }
      cout << endl;
   }
   cout << endl;
}

template<class T>
void foo(valarray<T>& vala, gslice& gs)
{
   size_t nRows = gs.size()[0];
   size_t nCols = gs.size()[1];
   valarray<T> varesult = vala[gs];
   print2d(varesult, nRows, nCols);
}

float Norm(Complex_f cf)
{
   return cf.real() * cf.real() + cf.imag() * cf.imag();
}

void convertComplexToFloat1(VCF_t& vac, VF_t& vaf)
{
   for(size_t i=0; i<vac.size(); ++i)
   {
      vaf[i] = Norm(vac[i]);
   }
}

void convertComplexToFloat2(VCF_t& vac, VF_t& vaf)
{
   std::transform(&vac[0], &vac[vac.size()], &vaf[0], Norm);
}

void convertComplexToFloat3(VCF_t &vac, VF_t &vaf)
{
   // RX: Lambda conversion function
   auto func = [](Complex_f f){return norm<float>(f);};
   std::transform(&vac[0], &vac[vac.size()], &vaf[0], func);
}

void convertComplexToFloat4(VCF_t &vac, VF_t &vaf)
{
   VCF_t normVac = vac * vac.apply(conj<float>);

   // RX: Lambda conversion function
   auto func = [](Complex_f f){ return real<float>(f);};
   std::transform(&normVac[0], &normVac[vac.size()], &vaf[0], func);
}

int main()
{
   const int M=5, N=7;
   const Complex_f vacFill(3.0, 4.0);
   VCF_t vac(vacFill, M*N);

   gslice gsOrig = gslice2DSet(0, M,N, N,1);
   gslice gs = gslice2DSet(8, 3,4, N,1);
   vac[gs] = Complex_f(30,40);

   foo(vac, gsOrig);
   foo(vac, gs);

   VF_t vaf(M*N);
   gs = gslice2DSet(9, 3,4, N,1);
   foo(vac, gs);

   vaf = 1.0;
cout << "v.1" << endl;
   convertComplexToFloat1(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.2" << endl;
   convertComplexToFloat2(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.3" << endl;
   convertComplexToFloat3(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.4" << endl;
   convertComplexToFloat4(vac, vaf);
   foo(vaf, gsOrig);

}

Open in new window


Success	time: 0 memory: 3232 signal:0
 (3,4) (3,4) (3,4) (3,4) (3,4) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (3,4) (3,4) (3,4) (3,4) (3,4) (3,4)

 (30,40) (30,40) (30,40) (30,40)
 (30,40) (30,40) (30,40) (30,40)
 (30,40) (30,40) (30,40) (30,40)

 (30,40) (30,40) (30,40) (3,4)
 (30,40) (30,40) (30,40) (3,4)
 (30,40) (30,40) (30,40) (3,4)

v.1
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.2
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.3
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.4
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

Open in new window


https://ideone.com/xyp8EU

I've used C++11 lamdas just for this example but I'm sure you're capable of converting them to normal function objects if you are using C++03 :)
phoffric\Author Commented:
>> Your functors are wrong. They need to take type Complex_f and return type float.
I agree, and that is what I was trying to do, and it worked for the norm function.

In 2003 C++ spec are these specs:
template<class T> T real(const complex<T>& x);
  Returns: x.real().

template<class T> T norm(const complex<T>& x);
  Returns: the squared magnitude of x.
I set T to be a float, so I thought I had this profile:
   float real(const complex<float >& x)
What actually did I have, if not the above?

The norm<float> function worked in both VS 2010 and g++, but the real<float> only worked in VS 2010. Since the real() function returns x.real(), which is a float, I thought the real() function should work in both compilers, just as the norm function did. Is one of these two compilers broken?
evilrixSenior Software Engineer (Avast)Commented:
It looks like C++11 introduced additional overloads for these functions:

26.4.9 Additional overloads [cmplx.over]
1 The following function templates shall have additional overloads:
arg, norm, conj, proj, imag, real

It looks like these additional overloads make your original code ambiguous.

Visual Studio 2010 isn't C++11 friendly but gcc (after 4.7) is and so you'll need to be specific as to which you wish to use by making use of static cast on the function pointer.

I'd strongly suggest upgrading from VC2010. We're just about to see VC2015 come out (in fact, the final RC is already production ready). From VC2015 onwards, there are no longer "Express" editions, instead you have a Community edition, which is pretty much a fully functional Visual Studio with all the (non-enterprise) stuff you'd get with Visual Studio Pro.

I'd also strongly suggest embracing C++11 otherwise you are going to start hitting more and more of these kinds of issues. It just doesn't make sense to force your projects to use a standard that is now 12 years old, where the current standard is 4 years old and where the new standard (C++14) is just about to be ratified.

The following code is C++03 and C++11 compliant and should resolve your problem.

https://ideone.com/2BaphP

#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
using namespace std;

typedef complex<float> Complex_f;
typedef valarray<Complex_f> VCF_t;
typedef valarray<float> VF_t;

gslice gslice2DSet(size_t start, size_t dim1, size_t dim2, size_t stride1, size_t stride2)
{
   size_t lengths[]= {dim1,    dim2};
   size_t strides[]= {stride1, stride2};

   gslice gs (
      start,
      valarray<size_t>(lengths,2),
      valarray<size_t>(strides,2));

   return gs;
}

template<class T>
void print2d(valarray<T> &v, size_t nRow, size_t nCol) {
   for(size_t r = 0; r < nRow; ++r)
   {
      for(size_t c = 0; c < nCol; ++c)
      {
         cout << ' ' << v[r*nCol + c];
      }
      cout << endl;
   }
   cout << endl;
}

template<class T>
void foo(valarray<T>& vala, gslice& gs)
{
   size_t nRows = gs.size()[0];
   size_t nCols = gs.size()[1];
   valarray<T> varesult = vala[gs];
   print2d(varesult, nRows, nCols);
}

float Norm(Complex_f cf)
{
   return cf.real() * cf.real() + cf.imag() * cf.imag();
}

void convertComplexToFloat1(VCF_t& vac, VF_t& vaf)
{
   for(size_t i=0; i<vac.size(); ++i)
   {
      vaf[i] = Norm(vac[i]);
   }
}

void convertComplexToFloat2(VCF_t& vac, VF_t& vaf)
{
   std::transform(&vac[0], &vac[vac.size()], &vaf[0], Norm);
}

void convertComplexToFloat3(VCF_t &vac, VF_t &vaf)
{
   std::transform(&vac[0], &vac[vac.size()], &vaf[0],
      static_cast<float(*)(std::complex<float> const &)>(&std::norm<float>));
}

void convertComplexToFloat4(VCF_t &vac, VF_t &vaf)
{
   VCF_t normVac = vac * vac.apply(conj<float>);
   std::transform(&normVac[0], &normVac[vac.size()], &vaf[0],
      static_cast<float(*)(std::complex<float> const &)>(&std::real<float>));
}

int main()
{
   const int M=5, N=7;
   const Complex_f vacFill(3.0, 4.0);
   VCF_t vac(vacFill, M*N);

   gslice gsOrig = gslice2DSet(0, M,N, N,1);
   gslice gs = gslice2DSet(8, 3,4, N,1);
   vac[gs] = Complex_f(30,40);

   foo(vac, gsOrig);
   foo(vac, gs);

   VF_t vaf(M*N);
   gs = gslice2DSet(9, 3,4, N,1);
   foo(vac, gs);

   vaf = 1.0;
cout << "v.1" << endl;
   convertComplexToFloat1(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.2" << endl;
   convertComplexToFloat2(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.3" << endl;
   convertComplexToFloat3(vac, vaf);
   foo(vaf, gsOrig);

   vaf = 1.0;
cout << "v.4" << endl;
   convertComplexToFloat4(vac, vaf);
   foo(vaf, gsOrig);

}

Open in new window


Success	time: 0 memory: 3276 signal:0
 (3,4) (3,4) (3,4) (3,4) (3,4) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (30,40) (30,40) (30,40) (30,40) (3,4) (3,4)
 (3,4) (3,4) (3,4) (3,4) (3,4) (3,4) (3,4)

 (30,40) (30,40) (30,40) (30,40)
 (30,40) (30,40) (30,40) (30,40)
 (30,40) (30,40) (30,40) (30,40)

 (30,40) (30,40) (30,40) (3,4)
 (30,40) (30,40) (30,40) (3,4)
 (30,40) (30,40) (30,40) (3,4)

v.1
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.2
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.3
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

v.4
 25 25 25 25 25 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 2500 2500 2500 2500 25 25
 25 25 25 25 25 25 25

Open in new window

CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

evilrixSenior Software Engineer (Avast)Commented:
>> The norm<float> function worked in both VS 2010 and g++
Not for me it doesn't. I get the same error for both norm and real. I guess it depends on what version of g++ you are using. I'm using the very latest version of g++. Providing static casts for both should resolve the problem. If you were using C++11 I'd recommend the original code I posted (to use lambda), as it's much cleaner :)
phoffric\Author Commented:
I do have VS Community 2013 at home; but I am using VS 2010 at home since my current project does not use C++11.

My g++ version is 4.8.2. If I add the -std=c++11 compiler flag, then, like you, I get an error for the norm case.

Looks like C++11 g++ compiler is not upward compatible with legacy C++03 code.
phoffric\Author Commented:
I copied your code into Cygwin. I didn't get an error with norm, but did get one with real:
$ g++  -O2 -Wall valarray_evilrix.cpp
valarray_evilrix.cpp: In function ‘void convertComplexToFloat4(VCF_t&, VF_t&)’:
valarray_evilrix.cpp:74:75: error: invalid static_cast from type ‘<unresolved overloaded function type>’ to type ‘float (*)(const std::complex<float>&)’
       static_cast<float(*)(std::complex<float> const &)>(&std::real<float>));

Open in new window


No errors if I add the -std=c++11 flag. (Too bad I am not allowed to use that at work - well, I can always ask. Also, we're using an older g++ version there, so I will give this a try at work tomorrow, and see what g++ has to say about this.)
phoffric\Author Commented:
I have a question on this code:
std::transform(&normVac[0], &normVac[vac.size()], &vaf[0],
      static_cast<float(*)(std::complex<float> const &)>(&std::real<float>));

Open in new window

Why use the & here:
(&std::real<float>)

Open in new window

What does it mean to apply &std::real<float> to each element of normVac?
phoffric\Author Commented:
In none of my projects in the last 4 years was C++11 an option. Each project was building upon existing c++03 code. (In one project, some experimental work was being done converting to c++11 to see how performance was affected.)
evilrixSenior Software Engineer (Avast)Commented:
>> Why use the & here:
In this case the & is optional, it's only mandatory when getting the address of a member function pointer; however, I like my code to be explicit in its self documentation and so I always use the & to show I really did mean to take the address of the function and haven't just missed off the brackets.

>> What does it mean to apply &std::real<float> to each element of normVac?
Exactly the same as applying std::real<float>

>> (In one project, some experimental work was being done converting to c++11 to see how performance was affected.
I wouldn't expect performance to be affected on bit (at least not detrimentally). The core language is the same and the way it compiles is the same, it's just that C++11 adds a whole bunch of extra (very useful) features.
phoffric\Author Commented:
Pasted your code in http:#a40795344  and selected C++4.3.2, and got the same compiler error. Maybe my g++ is not C++03 compliant. I will give it a try later at work. If you have a fix for this, I will try both. Thanks.
https://ideone.com/mGDqyl
prog.cpp: In function 'void convertComplexToFloat4(VCF_t&, VF_t&)':
prog.cpp:74: error: invalid static_cast from type '<unresolved overloaded function type>' to type 'float (*)(const std::complex<float>&)'

Open in new window

evilrixSenior Software Engineer (Avast)Commented:
Hmmm, it seems older versions of gcc seem to return a const reference rather than a value for real:

https://ideone.com/hzbzgJ

This doesn't appear to match with the C++03 standards documentation. that said, 4.3 is a pretty old version of gcc so it's quite possible that such an old version was less compliant!

I think your safest bet is to create wrapper functors and avoid trying to resolve the prototypes statically. In this way you know our code will always work.

Example with old and new gcc

https://ideone.com/j8NFer (C++14)
https://ideone.com/TBj5kw (C++ 4.3.2)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
phoffric\Author Commented:
Even the more recent g++ had the same problem:
$ g++ --version
g++ (GCC) 4.8.2

A little surprised that I can't get one set of code to be portable on both platforms by using built-in functions. So, wrapper functors is the way I will go. BTW, I tried the norm at work using Intel compiler, and it barfed. I had also tried the VS 2010 /Za option which worked so well in my other question, but the results were many and unreadable to me.
phoffric\Author Commented:
Thanks Rick for interpreting the error messages and figuring out how to get this to work using built-in functions using an older g++ compiler.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.