2012-10-06 30 views
6

Bằng cách nào đó tôi thích các chương trình "ngắn nhất" này hiển thị vấn đề (cơ bản?). Khi kiểm tra một số mã mẫu trong VS2008 lỗi này xuất hiện (nó cũng đã được xác nhận cho VS2010 và VS2012, xem bên dưới):Lỗi biên dịch VS C2752 ("nhiều hơn một phần chuyên môn phù hợp") trong STL

c: \ program files (x86) \ microsoft visual studio 9.0 \ vc \ include \ xmemory (225): lỗi C2752: 'std :: _ Ptr_cat_helper < _T1, _T2>': nhiều hơn một đặc tả từng phần phù hợp với danh sách mẫu tranh luận

with 
    [ 
     _T1=const float (**), 
     _T2=const float (**) 
    ] 

tôi có thể tóm tắt các vấn đề để ba dòng sau :

#include <vector> 
typedef float TPoint[3]; 
std::vector<TPoint const*> points; // error C2752 

Lưu ý rằng sau đây là tất cả ok

#include <vector> 
#include <list> 
typedef float TPoint[3]; 
// these similar usages of TPoint are all ok: 
std::vector<TPoint*> points; // no error 
TPoint const* points1[2]; 
std::list<TPoint const*> points2; 

tôi đã cố gắng để sửa chữa xutility bằng cách cung cấp thêm mẫu spezializations cho struct _Ptr_cat_helper - mà không may mắn. Bất kỳ ý tưởng gì đi sai? Hoặc làm thế nào để làm việc xung quanh mà không mất const?

+1

Đừng có VS cài đặt trước mặt tôi, nhưng nó hoạt động với GCC. Bạn có thể đã tìm thấy một lỗi trong lib chuẩn của họ. –

+0

Nâng cấp VS hiện không khả thi: chúng tôi phụ thuộc vào dll (sử dụng các thành phần MFC) từ các nhóm khác ... Nhưng sẽ rất tuyệt khi biết nếu ba dòng trên biên dịch trên VS2010 – coproc

+0

Xin lỗi, nó không biên dịch, đó là lý do tại sao tôi đã xóa nhận xét đó. Tuy nhiên, hoàn toàn không rõ nguyên tố của vec tơ là gì. Một con trỏ đến một mảng của ba yếu tố của const nổi? – Xeo

Trả lời

8

Vấn đề thực sự là một sự mơ hồ trong một chuyên môn hóa từng phần:

Bên trong, bộ cấp phát sử dụng một số lập trình meta (_Ptr_cat) để xác định xem dtor là được kêu gọi các phần tử của vector (hoặc không làm gì cả). Metaprogramming này cố gắng phân biệt một số trường hợp bằng cách sử dụng một phần chuyên môn hóa. _Ptr_cat sử dụng _Ptr_cat_helper đang được chuyên biệt về loại con trỏ của người cấp phát vector - số value_type của vectơ là TPointer const* == const float (*)[3], do đó trình phân bổ vectơ có kiểu con trỏ const float(**)[3].

Khi bạn sử dụng std::vector < const float(*)[3] >, thông báo lỗi chứa phần [3], trong khi sử dụng std::vector < TPoint const* >, các [3] không được hiển thị o.o

_Ptr_cat hy vọng hai đối số mẫu cùng loại với khả năng khác nhau c-vòng loại, ví dụ float*, float const*. Bây giờ, hai loại đầu vào là cả hai const float (**)[3]. MSVC giải quyết chúng một cách mơ hồ cho các chuyên ngành của _Ptr_cat_helper: Ty**, Ty const** và/hoặc Ty**, Ty**. Tôi đã xác minh rằng bằng cách viết một ví dụ nhỏ bắt chước chuyên môn từng phần của _Ptr_cat_helper (chỉ các mẫu đơn thuần, không có tham chiếu STd Lib).

Tuy nhiên, tôi không thể giải thích tại sao điều này xảy ra. Kỳ lạ thay, không có sự mơ hồ khi thiết lập một ví dụ chỉ sử dụng một thông số chuyên môn - const float(**)[3] được giải quyết thành Ty const** với Ty = float const[3] như mong đợi.

Cảm ơn Peter Alexander, tôi cũng đã thử ví dụ đơn giản của tôi (2 tham số mẫu) với g ++, và nó hoạt động như mong đợi, không mơ hồ. Có lẽ điều này có thể là một vấn đề trình biên dịch?

Hãy để tôi đề xuất một số biện pháp khắc phục:

  • Nếu bạn thực sự muốn thay đổi các lib chuẩn MSVC, bạn có thể thêm một chuyên môn hóa _Ptr_cat_helper < const Ty (**)[3], const Ty (**)[3] > mà phù hợp chính xác và giải quyết sự mơ hồ. Thật không may, bạn phải cung cấp kích thước một cách rõ ràng (3).
  • Không sử dụng mảng tại đây. Sử dụng std::array (có sẵn trong tr1 trong VS08) hoặc cấu trúc hoặc gợi ý đơn giản (float const* thay vì float const[3])
  • sử dụng một wrapper đơn giản:

    template < typename T > struct wrapper { T wrapped; } 
    std::vector < wrapper <TPoint> const* > m; 
    

    hoạt động tốt đối với tôi.

Edit: đây là ví dụ tôi sử dụng:

#include <typeinfo> 
#include <iostream> 

template < typename T1, typename T2 > 
struct Spec 
{ 
    static const char* check() { return "plain"; } 
    typedef void Value; 
}; 

#define MAKE_SPEC(ARG0, ARG1) \ 
template < typename T > \ 
struct Spec < ARG0, ARG1 > \ 
{ \ 
    static const char* check() { return #ARG0 ", " #ARG1; } \ 
    typedef T Value; \ 
} 

MAKE_SPEC(T**, T**); 
MAKE_SPEC(T**, T const**); 
// can do more, but need not to.. 

int main() 
{ 
    typedef Spec < const float(**)[3], const float(**)[3] > MySpec; 

    std::cout << MySpec::check() << " -- " << typeid(MySpec :: Value).name(); 
} 
+0

'Có thể đây có thể là vấn đề về trình biên dịch' - tôi cho rằng đó là sự cố thư viện. Vẫn còn 1 để phân tích – sehe

+0

Như ví dụ nhỏ tôi đã viết biên dịch tốt với g + + và không phải với MSVC, tôi kết luận đây không phải là vấn đề thư viện chủ yếu. Tôi đã nhấn một số lỗi trình biên dịch (đã được xác nhận), và biết đây là những lỗi thực sự hiếm - do đó cố gắng xây dựng nó một cách bảo thủ. – dyp

+1

Huh? Việc triển khai thư viện hoàn toàn khác nhau ... Tôi không nói rằng nó không thể là một vấn đề trình biên dịch, nhưng cho đến khi bạn, ví dụ, hiển thị GCC + STLPort biên dịch điều này, trong khi MSVC + STLPort thì bạn không có ít nền tảng chưa – sehe

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