Podczas kompilacji (Microsoft Visual C ++ 2005 Express) ten fragment kodu:
struct A
{
template< typename T > static A Foo( void ) { return A(); }
struct S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
A ( *m_funcFoo )( void );
};
};
int main(int argc, char* argv[])
{
A::S::GetInstance< int >();
}
Pojawia się błąd C2440:
"=": nie można przekonwertować z "A (__cdecl *) (void)" na "A (__cdecl *) (void)"
To nie ma dla mnie sensu. Dwa typy nazwane w tekście błędu są oczywiście takie same.
Również przy zmianie Foo
zwraca wartość do int
, nie ma takiego błędu.
Czy to błąd, czy robię coś nie tak?
EDYTOWAĆ :
Więc jeśli to błąd, czy ktoś wie, jak rozwiązać ten problem? Może za pomocą rzutów? Potrzebuję tego kodu do kompilacji ...
To błąd kompilatora. VC ++ robi coś bardzo dziwnego.
Na przykład generuje to bardzo inny komunikat o błędzie:
struct A
{
template< typename T > static struct A Foo( void ) { return A(); }
struct S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
A ( *m_funcFoo )( void );
};
};
sourceFile.cpp(5) : error C3856: 'A::Foo': class is not a class template
A to działa:
struct X {};
struct A
{
template< typename T > static X Foo( void ) { return X(); }
struct S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
X ( *m_funcFoo )( void );
};
};
Najwyraźniej to się myli z tym imieniem A
, co powinno odnosić się do klasy bazowej.
Dodanie typedef nie pomogło, ani nie przekazuje deklaracji struct A
, ani nie kwalifikuje się jako nazwa ::A
lub struct A
.
Dziwne, VC ++ 7 kompiluje to dobrze.
Obejście: Zmiana w następujący sposób:
struct A
{
template< typename T > static A Foo( void ) { return A(); }
struct S;
};
struct A::S
{
template< typename T > static S GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
A ( *m_funcFoo )( void );
};
odwraca wynik, teraz VC ++ 8 kompiluje ok, a VC ++ 7 generuje ten sam komunikat o błędzie.
Myślę, że istnieje problem tożsamości typu między niekompletnym typem a tym samym typem po zakończeniu.
Wszystkie testy są uruchamiane przy użyciu Dinkumware Multi-Compiler Test Tool
Nie jestem pewien, czy jest to błąd kompilatora, czy nie, ale przynajmniej jest to udokumentowane msdn.
Nie mam pod ręką kompilatora z 2005 roku, ale vs2010 kompiluje twój kod, jeśli napisze to tak:
struct A
{
template< typename T > static A Foo( void ) { return A(); }
struct S
{
A ( *m_funcFoo )( void );
template< typename T > static S GetInstance( void );
};
};
template< typename T >
A::S A::S::GetInstance( void )
{
S Result;
Result.m_funcFoo = &A::Foo< T >;
return Result;
}
Wygląda jak błąd - kompiluje się dobrze na Comeau (http://www.comeaucomputing.com/tryitout).
Próbowałem wyśledzić problem, a teraz wydaje się, że nie jest nawet konieczne posiadanie szablonowych funkcji lub zagnieżdżonych struktur w celu wygenerowania tego dziwnego błędu.
struct A
{
typedef A ( * SimpleFuncPtr )( void );
static void Foo( void )
{
SimpleFuncPtr func1 = 0; // Ok.
SimpleFuncPtr func2 = func1; // Ok.
A ( * func3 )( void ) = func1; // C2440 on both VS2005 and VS2010
}
};
Patrząc na powyższy fragment kodu staje się oczywiste, że jest to rzeczywiście błąd kompilatora (moim zdaniem).