2009-12-22 22 views
6

Tôi đang viết một thư viện giao diện cho phép truy cập vào các biến trong bảng (đến độ sâu vô hạn về mặt lý thuyết) trong một đối tượng thuộc loại regula::State. Tôi đang thực hiện điều này bằng cách quá tải operator[] trong một lớp, sau đó trả về một lớp khác cùng lớp đó và gọi lại operator[] nếu cần. Ví dụ:Tại sao g ++ nói 'không phù hợp cho ‘toán tử =’ khi rõ ràng, và Visual Studio có thể thấy rằng có?

regula::State t; 
t["math"]["pi"] = 3.14159; 

Trên đây là nghĩa vụ phải đặt giá trị 3.14159 trong biến pi trong bảng math. Về cơ bản, nó thực hiện điều này bằng cách t trả về một đối tượng proxy đại diện cho math, trả về một đối tượng proxy khác đại diện cho pi, mà chúng ta thực sự lưu biến đó. Nội bộ của điều này không thực sự liên quan đến câu hỏi, nhưng đây là tiêu đề hàm.

LObject LObject::operator[] (const std::string name); 

Về cơ bản, trong ví dụ trên, chương trình nên gọi t 's operator[] với chuỗi "math" và trở về đối tượng khác, và sau đó gọi đó là đối tượng của operator[] với chuỗi "pi", mà trả về đối tượng cuối cùng, và sau đó gán giá trị cho giá trị đó bằng cách sử dụng operator=.

template <typename T> 
T LObject::operator= (const T& value); 

T trả lại chỉ là bản sao của value được chuyển.

Bây giờ, mã của tôi tạo ra lỗi NO trong Visual C++ 2008 và hoạt động hoàn hảo. Nhưng khi tôi cố gắng để biên dịch nó trên Linux với g++, tôi nhận được lỗi sau:

../../test/regula-test.cpp:100: error: no match for ‘operator=’ in 
‘L.regula::State::operator[](std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >(((const char*)"Numbers"), ((const std::allocator<char>&)((const 
std::allocator<char>*)(& std::allocator<char>()))))) = Numbers’ 
../../include/regula.hpp:855: note: candidates are: regula::LObject& 
regula::LObject::operator=(const regula::LObject&) 

Đối với một số lý do, g++ dường như cố gắng gọi operator= trên operator[], chứ không phải trên các đối tượng quay trở lại như nó là vụ được.

tôi thực sự có thể sửa lỗi này bằng cách thay thế các kiểu trả về operator= với void:

template <typename T> 
/*T*/ void LObject::operator= (const T& value); 

Nhưng điều này không phải là thích hợp hơn, và bên cạnh đó, tôi có lỗi tương tự ở một số vị trí khác có tương tự như quá tải operator==:

../../test/regula-test.cpp:153: error: no match for ‘operator==’ in ‘pi == 
L.regula::State::operator[](std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >(((const char*)"pi"), ((const std::allocator<char>&)((const 
std::allocator<char>*)(& std::allocator<char>())))))’ 

Tôi không hiểu tại sao lỗi này xảy ra trong g ++ hoặc tại sao nó không xuất hiện trong Visual C++. Bất cứ ai có thể làm sáng tỏ điều này hoặc đề nghị bất kỳ giải pháp?

+4

bài viết mã thực. Mẫu của bạn bị hỏng. 'regula :: State t [" math "] [" pi "] = 3.14159;' không thể là một câu lệnh C++ hợp lệ. Tuyên bố "cố định" của 'toán tử =' của bạn cũng bị hỏng, bởi vì bây giờ không có 'T' ở đó – AnT

+0

@AndreyT: Tôi xin lỗi, dòng đó đã bị cắt bớt khi nó không nên có. Tôi đã cố định mẫu được đề cập. – pdusen

+2

Bạn có thể đun sôi nó xuống một đoạn mã nhỏ thể hiện lỗi này không? – Eclipse

Trả lời

6

Mục 5.17 của tiêu chuẩn ISO nói

There are several assignment operators, all of which group right-to-left. All require a modifiable lvalue as their left operand, and the type of an assignment expression is that of its left operand. The result of the assignment operation is the value stored in the left operand after the assignment has taken place; the result is an lvalue.

bạn operator= lợi nhuận không chỉ là loại sai, nhưng thậm chí không một giá trị trái. Giả sử thông báo lỗi của GCC không bao gồm bất kỳ ứng cử viên nào khác ngoài operator=(const regula::LObject&), GCC đã bỏ qua hoàn toàn tình trạng quá tải của bạn. Các operator= nó đề cập đến là mặc định, tự động tạo ra chức năng.

Trong nháy mắt thứ hai, operator[] cũng phải trả lại tham chiếu. Như được viết, không có biểu thức gán nào giống như ví dụ của bạn nên hoạt động.

Vì vậy, bạn nên có chức năng

LObject &LObject::operator[] (const std::string name); 

template <typename T> 
LObject &LObject::operator= (const T& value); 
+0

Đúng là cách toán tử = được khai báo là sai, nó không nhất thiết đúng là toán tử [] được khai báo sai. Trong thực tế, sự chuyên môn hóa cho ':: std :: vector ' định nghĩa toán tử [] để trả về một _Bit_reference (không phải là một tham chiếu thực). _Bit_reference lần lượt là một lớp định nghĩa toán tử '_Bit_reference & _Bit_reference :: của riêng nó = (bool x)'. – Omnifarious

+0

Toán tử [] của anh ta hợp lệ; toán tử [] không bắt buộc phải trả về một giá trị ở xa như tôi nhớ (không tìm kiếm nó ngay bây giờ). Điểm là, anh ấy * sử dụng * nó như một giá trị. – Potatoswatter

+0

Vâng, kết quả của ':: std :: vector :: toán tử []' được thiết kế để được sử dụng như một giá trị quá, và nó trả về một tạm thời giống như của mình. – Omnifarious

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