6

Chúng tôi đang di chuyển sang Sun Studio 12.1 và với trình biên dịch mới [CC: Sun C++ 5.10 SunOS_sparc 2009/06/03]. Tôi đang nhận được lỗi biên dịch khi biên dịch mã được biên dịch tốt với phiên bản trước của Sun Compiler [CC: Sun WorkShop 6 cập nhật 2 C++ 5.3 2001/05/15].Lỗi biên dịch mẫu trong Sun Studio 12

Đây là lỗi biên dịch tôi nhận được.

"Sample.cc": Error: Could not find a match for LoopThrough(int[2]) needed in main(). 1 Error(s) detected. *** Error code 1.

Mã sản phẩm:

#include <iostream> 

#define PRINT_TRACE(STR) \ 
std::cout << __FILE__ << ":" << __LINE__ << ":" << STR << "\n"; 

template<size_t SZ> 
void LoopThrough(const int(&Item)[SZ]) 
{ 
    PRINT_TRACE("Specialized version"); 
    for (size_t index = 0; index < SZ; ++index) 
    { 
     std::cout << Item[index] << "\n"; 
    } 
} 


/*  
    template<typename Type, size_t SZ> 
    void LoopThrough(const Type(&Item)[SZ]) 
    { 
     PRINT_TRACE("Generic version");   
    } 
*/ 



int main() 
{ 
    { 
     int arr[] = { 1, 2 }; 
     LoopThrough(arr);  
    } 
} 

Nếu tôi bỏ ghi chú mã với phiên bản Generic, mã biên dịch tốt và phiên bản generic được gọi. Tôi không thấy vấn đề này với MSVC 2010 với các phần mở rộng bị vô hiệu hóa và trường hợp tương tự với ideone here. Phiên bản chuyên biệt của hàm được gọi. Bây giờ câu hỏi là, đây có phải là một lỗi trong Sun Compiler không?

Nếu có, cách chúng tôi có thể gửi báo cáo lỗi?

+1

Việc xóa const lẽ workarodun nó? – PlasmaHH

+0

Có. Loại bỏ const hoặc thêm const vào int arr [] là công việc xung quanh. Nhưng, muốn biết nếu đây là lỗi trong trình biên dịch hay hiểu biết của tôi là sai. – Jagannath

+2

Rất có thể nếu các phiên bản mới nhất của clang, gcc, comeau và msvc đồng ý, thì đó là lỗi trong SunCC. Cũng lưu ý rằng SunCC là (trong) nổi tiếng là buggy. Điều này dẫn đến câu hỏi: tại sao không sử dụng gcc? – PlasmaHH

Trả lời

2

Trình biên dịch không tuân theo các tiêu chuẩn trong trường hợp này và là lỗi. Hãy xem lại các phần liên quan.

đầu tiên từ 13,3/3 ta có:

...

— First, a subset of the candidate functions—those that have the proper number of arguments and meet certain other conditions—is selected to form a set of viable functions (13.3.2).

— Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function.

Vì vậy, cả hai chức năng có cùng một số đối số và được coi là ứng cử viên. Bây giờ chúng ta phải tìm ra chức năng khả thi tốt nhất, trong

13.3.3:

let ICSi(F) denote the implicit conversion sequence that converts the ith argument in the list to the type of the ith parameter of viable function F. 13.3.3.1 defines the implicit conversion sequences and 13.3.3.2 defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another

Sau đó, chúng tôi có

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

— for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

— F1 is a nontemplate function and F2 is a template function specialization, or, if not that,

— F1 and F2 are template functions, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.5.2, or, if not that,

Hai chức năng đều bình đẳng cho các quy tắc đầu tiên (thêm const), và quy tắc thứ hai không áp dụng (cả hai đều là mẫu). Vì vậy, chúng tôi chuyển sang quy tắc thứ ba. Từ 14.5.5.2 (mà tôi sẽ báo giá nếu được yêu cầu), chúng tôi biết rằng phiên bản const int của chức năng chuyên biệt hơn phiên bản const Item và do đó, kết quả tốt nhất là quá tải const int, sau đó sẽ được gọi.

sửa chữa tạm thời tốt nhất của bạn có lẽ là một tình trạng quá tải thứ hai:

template<size_t SZ> 
void LoopThrough(int (&Item)[SZ]) 
{ 
    LoopThrough(static_cast<const int (&)[SZ]>(Item)); 
} 
1

Trình biên dịch của bạn bị lỗi. Cả hai tình trạng quá tải đều có đối số mẫu của chúng được suy luận và độ phân giải quá tải nên chọn đối số chuyên biệt nhất. Vì vậy, ngoài việc nhận được một trình biên dịch mới, bạn có thể làm gì?

Trước tiên, sẽ rất hữu ích khi nhận ra rằng, với cả trình biên dịch phù hợp, thường không phải là một ý tưởng hay để có quá tải mẫu chức năng khác nhau. Xem ví dụ Mục 66 của C++ Coding Standards: 101 Rules, Guidelines, and Best Practices bởi Herb Sutter và Andrei Alexandrescu.

May thay, mục đó cũng gợi ý sửa chữa có thể xảy ra. Tất cả những gì bạn phải làm là định nghĩa một mẫu hàm duy nhất và để cho khuôn mẫu hàm đó giao công việc cho một đối tượng hàm mẫu lớp. Sau đó, bạn có thể chuyên về từng phần mẫu lớp này cho ints.

#include <iostream> 

#define PRINT_TRACE(STR) \ 
std::cout << __FILE__ << ":" << __LINE__ << ":" << STR << "\n"; 

namespace detail {  

// primary template 
template<typename Type, size_t SZ> 
class LoopThroughHelper 
{ 
public: 
    void operator()(const Type(&Item)[SZ]) 
    { 
     PRINT_TRACE("Generic version");   
    } 
}; 

// partial specialization for int arrays 
template<size_t SZ> 
class LoopThroughHelper<int, SZ> 
{ 
public: 
    void operator()(const int(&Item)[SZ]) 
    { 
     PRINT_TRACE("Specialized version"); 
     for (size_t index = 0; index < SZ; ++index) 
     { 
      std::cout << Item[index] << "\n"; 
     } 
    } 
}; 

} // namespace detail 

// one function template to rule them all 
template<typename Type, size_t SZ> 
void LoopThrough(const Type(&Item)[SZ]) 
{ 
    detail::LoopThroughHelper<Type, SZ>()(Item);   
} 

int main() 
{ 
    { 
     int arr[] = { 1, 2 }; 
     LoopThrough(arr);  
    } 
} 

Rất có thể, trình biên dịch sẽ căn chỉnh cuộc gọi đến đối tượng hàm và hoàn toàn tối ưu hóa tạm thời. Hy vọng rằng trình biên dịch của bạn cũng sẽ thực hiện đúng một phần chuyên môn hóa các mẫu lớp.

Output trên Ideone

+0

Vấn đề của OP là đặc biệt là chỉ với một mẫu mà nó không biên dịch được vì trình biên dịch sẽ không ràng buộc một mảng không const để const tham số mảng. –

+0

@MarkB Bất kể, nó chỉ đơn giản là phong cách tốt để có thêm indirection cho các đối tượng chức năng chuyên ngành thay vì nhiều quá tải chức năng. – TemplateRex