2011-12-23 49 views
11

Khi biên dịch (Microsoft Visual C++ 2005 Express) đoạn mã này:Không thể chuyển đổi từ loại x thành loại x?

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>(); 
} 

tôi nhận được một lỗi C2440:

'=': cannot convert from 'A (__cdecl *)(void)' to 'A (__cdecl *)(void)'

Điều đó không có ý nghĩa đối với tôi. Hai loại có tên trong văn bản lỗi rõ ràng là giống nhau. Ngoài ra, khi thay đổi giá trị trả về Foo thành int, không có lỗi như vậy.

Có phải là lỗi hoặc tôi đang làm điều gì sai?

EDIT: Vì vậy, nếu đó là một lỗi, không ai biết làm thế nào để giải quyết này? Có lẽ bằng cách sử dụng phôi? Tôi cần mã này để biên dịch ...

+4

Đó là lỗi! [....] –

+0

Lúc đầu, tôi nghĩ rằng đó là vì 'A (*) (void)' * khác * từ 'A (A :: *) (void)', nhưng không thể làm theo cách đó. – Griwes

Trả lời

4

Đó là lỗi trình biên dịch. VC++ đang làm điều gì đó rất lạ.

Ví dụ, điều này tạo ra một thông báo lỗi rất khác nhau:

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 

Và công trình này:

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); 
    }; 
}; 

Rõ ràng nó đang bối rối bởi những tên A, mà nên tham khảo các lớp cơ sở.

Thêm typedef không được trợ giúp, cũng không khai báo trước là struct A, cũng không đủ điều kiện tên là ::A hoặc struct A.

Rất kỳ quặc, VC++ 7 biên dịch tốt.

Cách giải quyết: Thay đổi nó như thế này:

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); 
}; 

đảo ngược kết quả, bây giờ VC++ 8 biên dịch ok và VC++ 7 tạo ra các thông báo lỗi tương tự.

Tôi nghĩ rằng có sự cố về loại danh tính giữa loại không hoàn chỉnh và cùng loại sau khi hoàn thành.

Tất cả các bài kiểm tra chạy bằng cách sử dụng Dinkumware Multi-Compiler Test Tool

1

Tôi không chắc đó có phải là lỗi trình biên dịch hay không, nhưng ít nhất nó được ghi lại trên msdn.
Tôi không có một trình biên dịch 2005 tại tay nhưng VS2010 biên dịch mã của bạn nếu viết nó như thế này:

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; 
} 
+0

Ồ, liên kết MSDN bằng tiếng Đức. – fefe

+0

@fefe không phải là nó không phải là – AakashM

+0

@mkaes Bạn đã thực sự khởi tạo 'A :: S :: GetInstance' (ví dụ bằng cách gọi nó)? Tôi đã kiểm tra mã của bạn trong cả hai VS2005 và VS2010 - nó vẫn là lỗi tương tự. – Baltram

0

tôi đã cố gắng để theo dõi các vấn đề xuống và bây giờ nó có vẻ như nó không phải là thậm chí cần thiết để có chức năng rập khuôn hoặc cấu trúc lồng nhau để tạo ra lỗi kỳ lạ này.

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 
    } 
}; 

Bằng cách nhìn vào đoạn mã trên, rõ ràng đây thực sự là lỗi trình biên dịch (theo ý kiến ​​của tôi).

+0

Vấn đề là với loại không đầy đủ và được mô tả trong liên kết được cung cấp bởi mkaes (nghĩa là vì kiểu không hoàn chỉnh tại thời điểm định nghĩa con trỏ hàm, trình biên dịch chọn một quy ước cuộc gọi cụ thể sau này được ghi đè lên khi loại đầy đủ được xác định) –

Các vấn đề liên quan