Reputation: 45
I'm in the process of porting some of my Linux programs to Windows. I would like to make sure my codes compile with both MinGW and Visual C++ 10 without too much #define
and #ifdef
magic. I've managed to work out most of the problems, except this one. I have a code similar to the following, which compiles fine with g++ 4.6.3 but not with Visual C++ 10:
#include <iostream>
#include <vector>
#include <array>
#include <algorithm>
#include <functional>
#include <cmath>
#include <iterator>
typedef unsigned char UINT8;
const UINT8 MAX_COLL = 10;
template< typename BaseT, typename ExpT >
struct fopow {
BaseT operator() ( BaseT base, ExpT exp ) const {
return std::pow( base, exp );
}
};
int main() {
using namespace std;
using namespace std::placeholders;
array<int, MAX_COLL> intCollection_init = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<int> intCollection( intCollection_init.begin(), intCollection_init.end() );
transform( intCollection.begin(), intCollection.end(),
ostream_iterator<int>( cout, " " ),
bind( fopow<int, int>(), 3, _1 )
);
cout << endl;
transform( intCollection.begin(), intCollection.end(),
ostream_iterator<int>( cout, " " ),
bind( fopow<int, int>(), _1, 3 )
);
cout << endl;
}
The compiler output is not even remotely intelligible to me:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
Test2.cpp C:\Program Files\Microsoft Visual Studio
10.0\VC\INCLUDE\xxresult(28) : error C2903: 'result' : symbol is neither a class template nor a function template
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(40) : see reference to class tem plate instantiation 'std::tr1::_Result_type2<__formal,_Fty,_Arg0,_Arg1>' being compiled
with
[
__formal=false,
_Fty=fopow<int,int>,
_Arg0=std::tr1::_Nil &,
_Arg1=std::tr1::_Nil &
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(597) : see reference to class te mplate instantiation 'std::tr1::_Result_of2<_Fty,_Farg0,_Farg1>' being compiled
with
[
_Fty=fopow<int,int>,
_Farg0=std::tr1::_Nil &,
_Farg1=std::tr1::_Nil &
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xrefwrap(28) : see reference to class tem plate instantiation 'std::tr1::_Result_of<_Ty>' being compiled
with
[
_Ty=fopow<int,int> (std::tr1::_Nil &,std::tr1::_Nil &)
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxbind1(273) : see reference to class tem plate instantiation 'std::tr1::result_of<_Fty>' being compiled
with
[
_Fty=fopow<int,int> (std::tr1::_Nil &,std::tr1::_Nil &)
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxbind0(10) : see reference to class temp late instantiation 'std::tr1::_Bind2<_Callable,_Arg0,_Arg1>::_Return<_Barg0,_Barg1,_Barg2,_Barg3,_Barg4,_B arg5,_Barg6,_Barg7,_Barg8,_Barg9>' being compiled
with
[
_Callable=std::tr1::_Callable_obj<fopow<int,int>,false>,
_Arg0=int,
_Arg1=std::tr1::_Ph<1>,
_Barg0=std::tr1::_Nil &,
_Barg1=std::tr1::_Nil &,
_Barg2=std::tr1::_Nil &,
_Barg3=std::tr1::_Nil &,
_Barg4=std::tr1::_Nil &,
_Barg5=std::tr1::_Nil &,
_Barg6=std::tr1::_Nil &,
_Barg7=std::tr1::_Nil &,
_Barg8=std::tr1::_Nil &,
_Barg9=std::tr1::_Nil &
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\functional(408) : see reference to class template instantiation 'std::tr1::_Bind_base<_Ret,_BindN>' being compiled
with
[
_Ret=std::tr1::_Notforced,
_BindN=std::tr1::_Bind2<std::tr1::_Callable_obj<fopow<int,int>,false>,int,std::tr1::_Ph<1>>
]
Test2.cpp(26) : see reference to class template instantiation 'std::tr1::_Bind_fty<_Fty,_Ret,_Bind N>' being compiled
with
[
_Fty=fopow<int,int>,
_Ret=std::tr1::_Notforced,
_BindN=std::tr1::_Bind2<std::tr1::_Callable_obj<fopow<int,int>,false>,int,std::tr1::_Ph<1>>
] C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(28) : error C2039: 'result' : is not a m ember of 'fopow<BaseT,ExpT>'
with
[
BaseT=int,
ExpT=int
] C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(28) : error C2143: syntax error : missin g ';' before '<' C:\Program Files\Microsoft Visual Studio
10.0\VC\INCLUDE\xxresult(28) : error C4430: missing type specifie r - int assumed. Note: C++ does not support default-int C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(28) : error C2039: 'type' : is not a mem ber of '`global namespace'' C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(28) : error C2238: unexpected token(s) p receding ';' C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(40) : error C2039: '_Type' : is not a me mber of 'std::tr1::_Result_type2<__formal,_Fty,_Arg0,_Arg1>'
with
[
__formal=false,
_Fty=fopow<int,int>,
_Arg0=std::tr1::_Nil &,
_Arg1=std::tr1::_Nil &
] C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(40) : error C2146: syntax error : missin g ';' before identifier '_Type' C:\Program Files\Microsoft Visual Studio
10.0\VC\INCLUDE\xxresult(40) : error C4430: missing type specifie r - int assumed. Note: C++ does not support default-int C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(40) : error C2602: 'std::tr1::_Result_of 2<_Fty,_Farg0,_Farg1>::_Type' is not a member of a base class of 'std::tr1::_Result_of2<_Fty,_Farg0,_Farg1
>'
with
[
_Fty=fopow<int,int>,
_Farg0=std::tr1::_Nil &,
_Farg1=std::tr1::_Nil &
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(40) : see declaration of 'std::t r1::_Result_of2<_Fty,_Farg0,_Farg1>::_Type'
with
[
_Fty=fopow<int,int>,
_Farg0=std::tr1::_Nil &,
_Farg1=std::tr1::_Nil &
] C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xxresult(40) : error C2868: 'std::tr1::_Result_of 2<_Fty,_Farg0,_Farg1>::_Type' : illegal syntax for using-declaration; expected qualified-name
with
[
_Fty=fopow<int,int>,
_Farg0=std::tr1::_Nil &,
_Farg1=std::tr1::_Nil &
]
I think the root of the problem is bind() or transform() but I don't know what exactly is wrong with the code (as it compiles fine without a single warning with g++). Anyone knows how to fix my code without resorting to prepocessor magics?
Upvotes: 2
Views: 1458
Reputation: 56986
std::bind
is not what you think it is in VS2010: it is in fact std::tr1::bind
, and uses std::tr1::result_of
, which is much less powerful than the compiler-assisted std::result_of
mandated by the C++11 standard.
In particular, don't try to use std::bind
with lambda-expressions in VS10.
You can resolve this here by having fopow
inherit std::binary_function<BaseT, ExpT, BaseT>
.
Upvotes: 2
Reputation: 76458
Add typedef BaseT result_type;
to the definition of fopow
. The template hackery that was needed in the days before decltype
is getting lost trying to figure out what the return type of fopow::operator()
is. (And, yes, you're right: it's getting lost in the bind()
call; specifically, the first one.)
Or, if you like, you can use the fix suggested by @ecatmur: derive from std::binary_function<BaseT, ExpT, BaseT>
. That will also add result_type
to the template, as well as first_argument_type
and second_argument_type
. bind
doesn't need the argument types.
Upvotes: 2