2011-11-10 35 views
5

Tôi hiện đang xem xét một số mã có thể được biên dịch trên các phiên bản mới hơn của GCC chứ không phải trên các phiên bản cũ hơn. Trong trường hợp của tôi, tôi đang sử dụng một số std::back_inserter đến std::copy một số dữ liệu từ một cấu trúc dữ liệu đến cấu trúc dữ liệu tùy chỉnh. Tuy nhiên, nếu tôi quên kiểu gõ typedef value_type & const_reference trong cấu trúc dữ liệu tùy chỉnh này, thì điều này sẽ không biên dịch trên GCC 4.4. Cùng một mã biên dịch và chạy tốt trên GCC 4.5.std :: back_inserter cần const_reference trên GCC cũ hơn. Tại sao?

Sự khác biệt giữa hai phiên bản trình biên dịch này, điều đó làm cho mã biên dịch trên một phiên bản nhưng không biên dịch trên phiên bản khác. Tôi đoán nó có một cái gì đó để làm với việc thực hiện C + + 11 được hoàn thành ít hơn nhiều trong GCC 4.4. Có lẽ một cái gì đó với decltype hoặc một từ khóa C++ 11 mới, tôi đoán vậy.

Mã này cũng đúng, nếu tôi sử dụng std::back_inserter mà không xác định loại const_reference? Tôi thường nghĩ rằng người ta phải thực hiện đầy đủ các typedefs (value_type, reference, const_reference vv) để tương thích với thư viện thuật toán STL? Hoặc tôi có thể giả định một cách an toàn rằng nếu mã của tôi biên dịch trong trường hợp này, tôi không gọi bất cứ điều gì nguy hiểm (ví dụ: di chuyển ngữ nghĩa, mà sẽ phá hủy cơ sở hạ tầng khác của tôi).

+0

Để ghi lại (để giúp người mới bắt đầu như tôi tiết kiệm thời gian): Sau khi tôi thêm 'typedef T & tham chiếu; typedef const T & const_reference; ' vào cấu trúc dữ liệu của tôi, lỗi c2039 cho back_inserter đã biến mất. –

Trả lời

6

Tiêu chuẩn (1998) cho biết std::back_insert_iterator cần Container::const_reference. Trong "24.4.2.1 Template lớp back_insert_iterator", [lib.back.insert.iterator], nó nói:

back_insert_iterator<Container>& 
operator=(typename Container::const_reference value); 

Tiêu chuẩn 2011 chỉ muốn Container::value_type,

back_insert_iterator<Container>& 
operator=(const typename Container::value_type& value); 
back_insert_iterator<Container>& 
operator=(typename Container::value_type&& value); 

Vì vậy, để phù hợp với cả hai phiên bản của tiêu chuẩn C++, xác định cả hai value_typeconst_reference_type.

Trong cả hai GCC 4.4.6 và 4.5.1, định nghĩa về operator= là giống hệt nhau (libstdc++-v3/include/bits/stl_iterator.h):

back_insert_iterator& 
    operator=(typename _Container::const_reference __value) 
    { 
    container->push_back(__value); 
    return *this; 
    } 

và tôi nhận được lỗi tương tự với cả hai trình biên dịch, có lẽ bạn sẽ cần phải kiểm tra lại nếu bạn đang sử dụng đúng phiên bản trình biên dịch.

+0

Cảm ơn bạn đã làm rõ. Trên 4.5.2 nó hoạt động mà không có kiểu dữ liệu, như tôi vừa xác minh. 4.4.4 vẫn cần nó. – LiKao

+1

@LiKao, trong các GCC gần đây, khả năng tương thích thư viện C++ 0x được bật theo mặc định. GCC4.5.2 hơi tương thích * nhiều hơn * so với GCC 4.4 ở chỗ nó sử dụng 'const_reference' chỉ khi tính tương thích bị vô hiệu hóa, trong khi 4.4 sử dụng nó một cách vô điều kiện. – chill

+0

@chill: Trích dẫn [tài liệu về phiên bản gcc hiện tại] (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Standards.html#Standards): 'Mặc định, nếu không có ngôn ngữ C++ tùy chọn phương ngữ được đưa ra, là -std = gnu ++ 98.'. Vì vậy, bạn có chắc chắn về những gì bạn nói không? –

1

Lý do mà bạn cần const_reference định nghĩa cho cấu trúc dữ liệu của bạn được vì toán tử gán trong GCC 4.4 cho một kiểu lập luận vế trái trong lớp std::back_insert_iterator được định nghĩa là:

template<class Container> 
back_insert_iterator<Container>& 
back_insert_iterator<Container>::operator= 
        (typename Container::const_reference value); 

Như vậy const_reference nhu cầu trở thành một số nhận dạng có thể phân giải trong loại lớp của bạn để tạo nhanh toán tử gán trong mẫu lớp std::back_insert_iterator.

Trong GCC 4.5, định nghĩa này của toán tử gán cho các đối số vế trái đã được thay đổi để

template<class Container> 
back_insert_iterator<Container>& 
back_insert_iterator<Container>::operator= 
       (const typename Container::value_type& value); 

để hỗ trợ mới C++ 11 đặc điểm kỹ thuật. Vì mã của bạn biên dịch chính xác với GCC 4.5, tôi giả sử bạn phải có value_type được xác định đúng cho cấu trúc dữ liệu của bạn.

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