`decltype`: функция, возвращающая тип` T`, преобразованная в `T &` для пользовательских типов (VS2010) - PullRequest
2 голосов
/ 06 января 2012

РЕДАКТИРОВАТЬ: GCC компилирует это просто отлично, это проблема VS2010.Спасибо, что указали мне на ideone.com!

При попытке скомпилировать следующее (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 );
}

Я получил предупреждение компилятора:

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.

Всеподходит для встроенного типа, но для пользовательского типа decltype(...) в функции шаблона FCall дает мне TA& вместо TA, и как FCall тип возвращаемого значения, и как локальная переменная в FCall,

Я не вижу логики за этим, и я думаю, что Стандарт говорит, что decltype(f()) должен дать точно тип возврата f().И это прекрасно работает для встроенных типов.Есть ли какой-то скрытый улов для пользовательских типов, или это просто игра со мной VS2010?

PS У меня нет доступа к GCC, может кто-нибудь, пожалуйста, проверить, компилируется ли GCC без предупреждений?

1 Ответ

1 голос
/ 06 января 2012

Это ошибка компилятора в VS2010. Этого не происходит ни в GCC (ideone.com), ни в Visual C ++ 11 Developer Preview.

Спасибо PlasmaHH и Xeo за ссылку на ideone.com и Джесси за информацию о состоянии ошибки в Visual C ++ 11 Developer Preview.

РЕДАКТИРОВАТЬ: просто продолжение: эта ошибка в VS2010 происходит, когда пользовательский тип имеет пользовательский конструктор. Если его нет (используется компилятор по умолчанию), ошибка не возникает.

...