2013-03-17 32 views
12

Tôi gặp phải sự cố khi chuyển một số mã vào MSVC, câu đố này giải đố tôi. Theo như tôi biết, mã phải hợp pháp, và Clang biên dịch nó rất tốt.Tại sao MSVC không biên dịch được chức năng mẫu này?

tôi đã thu hẹp nó xuống như sau:

enum E { 
    x 
}; 

template <typename T> 
struct traits { 
    static const E val = x; 
}; 

template <E e> 
struct S { 
    S(){}; 
}; 

template <typename T> 
S<traits<T>::val> foo(T t); 

int main() { 
    char c = 0; 
    foo(c); 
} 

Lưu ý rằng sau khi biên dịch, các mã được kỳ vọng sẽ tạo ra một mối liên kết lỗi (Tôi tước đi những định nghĩa của hàm foo để giữ mẫu tối thiểu), nhưng nó nên biên dịch sạch như xa như tôi biết.

Tuy nhiên, MSVC mang lại cho tôi lỗi này:

error C2893: Failed to specialize function template 'S::val> foo(T)'

Vì vậy, câu hỏi của tôi:

  • là MSVC bởi bất kỳ cơ hội đúng trong việc từ chối mã? (và nếu có, tại sao?)
  • nếu không, bất cứ ai có thể thu hẹp những gì nó đang làm sai? Như trong, nó là một tính năng ngôn ngữ mà họ không thực hiện ở tất cả (chẳng hạn như tra cứu tên hai giai đoạn cho các mẫu), hoặc "chỉ" một lỗi đơn giản trong việc thực hiện một tính năng mà họ yêu cầu hỗ trợ?

Tôi đã sao chép các vấn đề về VC++ 2010 và 2012.

+0

Có liên quan đến câu hỏi này từ hôm nay không? [Có bất kỳ đảm bảo nào về thứ tự thay thế trong một mẫu chức năng sau khi khấu trừ loại không?] (Http://stackoverflow.com/questions/15462336/is-there-any-guarantee-on-the-order-of-substitution- in-a-function-template-after) –

+0

@BoPersson: Dường như không liên quan đến tôi. Tôi không thể nghĩ ra bất cứ điều gì khác hơn là một lỗi ở đây. Btw nó hoạt động như mong đợi trên GCC 4.7.2 –

+0

Hơn nữa, nếu bạn thay 'enum' bằng' int' thì lỗi sẽ biến mất. Nó có vẻ là một lỗi liên quan đến 'enum's –

Trả lời

3

Sau khi chạy một vài thử nghiệm bản thân mình, điều này có vẻ là một lỗi biên dịch trong MSVC. Trong khi nó hoạt động tốt với GCC, MSVC cung cấp cho lỗi trình biên dịch khó hiểu và không hữu ích (giống với những người trong câu hỏi của bạn) khi bạn cố gắng sử dụng traits<T>::val bên trong các tham số mẫu cho trả lại S< E e >.

Điều thú vị là, khi bạn thay đổi S< E e > để lấy số nguyên thay vào đó, nó hoạt động. Hãy xem xét ví dụ này, giống hệt như của bạn với một số cách đặt tên khác nhau:

enum E { 
    x 
}; 

template <typename T> 
struct traits { 
    static const E val = x; 
}; 

template <E e> 
struct S { 
    S(){}; 
}; 

template <typename T> 
S< traits<T>::val > tricky(T t) { 
    return S< traits<T>::val >(); 
}; 

int main() { 
    char thiskidwhowalksaround = 0; 
    S<x> s = tricky(thiskidwhowalksaround); 
} 

Bây giờ, chúng ta hãy chỉ cần thay đổi một điều duy nhất:

template <int e> // int instead of E 
struct S { 
    S(){}; 
}; 

Chương trình sau đó biên dịch (liên kết, và chạy) một cách hoàn hảo đối với tôi . Nếu bạn cũng quay trở lại với bản gốc, và sau đó vượt qua trong một giá trị của E trực tiếp, như:

template <typename T> 
S<x> tricky(T t) { 
//^here 
    return S<x>(); // <-- here 
}; 

Sau đó, chương trình biên dịch tập tin. MSVC có vấn đề mà nó cắn bụi tại cố gắng để làm như sau:

traits<T>::val

nơi val là bất kỳ loại liệt kê. Tôi chắc chắn 99% đây là sự thiếu hụt trong Compiler. Điều này có vẻ là hoàn toàn được hình thành C + + vì vậy tôi không thể nói rằng GCC đang làm điều gì đó sai hoặc mở rộng-y bằng cách có đoạn mã ban đầu làm việc. Vì vậy, tốt nhất tôi có thể thu thập được là MSVC là thiếu trong trình biên dịch mạnh mẽ so với các đồng nghiệp của nó, nhưng một lần nữa.

Bạn có thể dừng đọc ở đây, vì bây giờ tôi sẽ dành một chút thời gian để đọc về trình biên dịch MSVC.

begin<rant> Nó không phải là VC++ đội là xấu hay C++ là xấu, nhưng từ những gì tôi thu thập đội biên dịch và các đội bóng thư viện chuẩn của Microsoft - tính thời điểm viết - là nhỏ so với các phòng ban khác. Nó làm tôi khó hiểu rằng một ngôn ngữ cơ bản và quan trọng và một phần cốt lõi của ngành công nghiệp của MS có ít nhân lực tương đối đến mức không thể theo kịp điều gì - trong cuộc đời ngắn ngủi của tôi - tôi thấy là một trong những tiêu chuẩn chuyển động chậm nhất trên thế giới. Tôi chắc chắn không phải là những người làm việc trong nhóm VC++, nhưng tôi rất bối rối vì sao không có nhiều người trong số họ làm việc để đưa C++ không chỉ lên tốc độ mà còn làm cho trình biên dịch hoạt động tốt hơn và tốt hơn khu vực sản phẩm. end<rant>

+0

Nó thực sự là một lỗi trình biên dịch. Tôi đã báo cáo nó trên [Connect] (https://connect.microsoft.com/VisualStudio/feedback/details/781537/failed-to-specialize-function-template#tabs), và họ chỉ ra rằng nó sẽ được sửa "trong bản phát hành tiếp theo của Visual C++ ".... Bất cứ khi nào đó là – jalf

+0

@ jalf: Hoan hô ...! Có lẽ. –

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