EDIT: GCC compiles it just fine, it’s VS2010 issue. Thanks for pointing me to ideone.com!
While trying to compile the following (VS2010):
#include <iostream>
template< typename PF01, typename PF02 >
inline auto FCall01( PF01 fCallee, PF02 && fParameter00 ) -> decltype( fCallee( std::forward< PF02 > ( fParameter00 ) ) )
{
decltype( fCallee( std::forward< PF02 > ( fParameter00 ) ) ) lResult( fCallee( std::forward< PF02 >( fParameter00 ) ) ); // offending line for Foo03
return ( lResult );
}
int gI = 0;
int & gCI = gI;
struct TA
{
int mData;
TA( int fData = 0 ) : mData( fData ) { }
TA( TA const & fA ) : mData( fA.mData ) { }
};
int Foo00( int & fA ){ return ( fA ); }
int & Foo01( int & ){ return ( gCI ); }
int const & Foo02( int & ){ return ( gCI ); }
TA Foo03( int & fA ){ return ( TA( fA ) ); }
int main( void )
{
decltype( FCall01( Foo00, gI ) ) l0( FCall01( Foo00, gI ) );
l0 = -1;
std::cout << gI << " : " << l0 << std::endl;
decltype( FCall01( Foo01, gI ) ) l1( FCall01( Foo01, gI ) );
l1 = -2;
std::cout << gI << " : " << l1 << std::endl;
decltype( FCall01( Foo02, gI ) ) l2( FCall01( Foo02, gI ) );
const_cast< int & > ( l2 ) = -3;
std::cout << gI << " : " << l2 << std::endl;
decltype( FCall01( Foo03, gI ) ) l3( FCall01( Foo03, gI ) );
l3.mData = -4;
std::cout << gI << " : " << l3.mData << std::endl;
return ( 0 );
}
I get a compiler warning:
Warning C4239: nonstandard extension used : 'initializing' : conversion from 'TA' to
'TA &'; A non-const reference may only be bound to an lvalue; see reference to function
template instantiation 'TA &FCall01<TA(__cdecl *)(int &),int&>(PF01,PF02) with
[PF01=TA(__cdecl *)(int &),PF02=int &]' being compiled.
Everything is fine for built-in type, but for user-defined type, decltype(...) in the template function FCall gives me TA& instead of TA, both as FCall return type and local variable in FCall.
I don’t see logic behind it, and I think Standard says decltype(f()) should give exactly return type of f(). And it works fine for built-in types. Is there some hidden catch for user-defined types or it’s just VS2010 playing tricks on me?
P.S. I don’t have access to GCC, could someone, please, check if GCC compiles is it without warnings?
It’s a compiler bug in VS2010. It does not happen in neither GCC (ideone.com) nor Visual C++ 11 Developer Preview.
Thanks to PlasmaHH and Xeo for the link to ideone.com, and Jesse for the info on the bug status in Visual C++ 11 Developer Preview.
EDIT: Just a follow-up: this bug in VS2010 happens when user-defined type has user-defined constructor. If it does not have one (compiler generated default is used), bug does not happen.