The following code compiles in MSVC++, but does not compile in GCC 4.5.1:
#include <iostream>
template< typename PT, bool pB >
struct TA
{
PT m;
TA( PT fT ) :
m( fT )
{
std::cout << "TA<" << pB << ">::TA() : " << m << std::endl;
}
PT operator()( PT fT )
{
std::cout << "TA<" << pB << ">::() : " << m << " and " << fT << std::endl;
return ( m );
}
};
template< typename PT >
PT Foo( PT fT )
{
std::cout << "Foo() : " << fT << std::endl;
return ( fT );
}
// Does not compile in GCC 4.5.1, compiles in MSVC++2010.
// Substitute TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > with
// TA< double, pB > to compile with GCC.
template< bool pB, typename PF, typename PP >
auto Func( PF fF, PP && fP, TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > && fA )
-> decltype( fF( std::forward<PP>( fP ) ) )
{
decltype( fF( std::forward<PP>( fP ) ) ) lResult( fF( std::forward< PP >( fP ) ) );
fA( lResult );
return ( lResult );
}
int main( void )
{
Func< true >( Foo< double >, -1.2, 2.1 );
return ( 0 );
}
The comment points to the problematic line and shows the fix (which is not really a fix from design point of view, just a compilation fix). Few questions:
-
Is MSVC++ correct to compile this?
-
If we were to change parameters’ order in
auto Func( PF fF, PP && fP, TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > && fA )
to
auto Func( PF fF, TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > && fA, PP && fP )
it would not compile, since compiler treats fP in TA< decltype( fF( std::forward<PP>( fP ) ) ), pB > as undeclared variable. Logically, does compiler really need to know fP at this point, does it not parse the whole declaration anyway, since it’s function with trailing return-type? Why can it not “skip” second function parameter and see if fP is declared in function declaration later? Or I’m missing something fundamental here (perhaps, some paragraph from the Standard)?
I believe MSVC is correct.
You cannot refer to a later parameter in the declaration of an earlier one, because the name is not yet in scope. In order to determine the type of your
fAparameter, the bothfPandfFmust be in scope so that thedecltypeexpression can be evaluated.If you explicitly specify the template parameters then it works with gcc:
That and the fact that specifying “double” directly as the parameter for
TAworks implies that the use of a dependent type for theTAparameter is preventing the type deduction forPFandPP. I can’t see why that would be though.