2016-10-03 35 views
9

Tôi đã gửi một lỗi GCC cho việc này, nhưng tôi muốn kiểm tra kỹ hơn điều này.Khởi tạo Brace so với Dấu ngoặc đơn

Hãy xem xét các chương trình sau:

#include <utility> 
template<typename T, typename A> 
void F(A&& a) { T(std::forward<A>(a)); } // Note:() syntax. 
int main() { int i; F<int&>(i); } 

và:

#include <utility> 
template<typename T, typename A> 
void F(A&& a) { T{std::forward<A>(a)}; } // Note: {} syntax. 
int main() { int i; F<int&>(i); } 

mới nhất Clang và MSVC trình biên dịch chấp nhận cả hai chương trình. GCC 5 và hơn thế nữa chấp nhận chương trình đầu tiên nhưng từ chối chương trình thứ hai, tuyên bố invalid cast of an rvalue expression of type 'int' to type 'int&'.

Đây có phải là lỗi của GCC không? Hoặc đây thực sự là một sự khác biệt giữa T{}T() trong ngữ cảnh trên (và do đó một lỗi trong Clang và MSVC)?

Edit:

Vấn đề này có thể được thu hẹp xuống trích đoạn đơn giản sau đây:

int i; (int&){i}; 

int i; (int&)(i); 
+0

Thậm chí bạn có thể xác định và khởi tạo tham chiếu giá trị không được đặt tên không? Lỗi này có vẻ không chính xác. – krzaq

+0

@krzaq: Tôi không hiểu tại sao không. Ngoài ra, tôi nhấn lỗi này trong biểu thức 'noexcept', vì vậy tôi muốn hiểu tình huống trong ngữ cảnh biểu thức. – alecov

+4

Đây là [vấn đề cốt lõi 1288] (http://wg21.link/cwg1288). GCC được cho là sẽ thực hiện giải pháp của mình, nhưng có lẽ nó không hoàn toàn cố định. –

Trả lời

6

Có hai vấn đề riêng biệt:

  • Tiêu chuẩn không rõ ràng T{x} nên làm gì cho loại tài liệu tham khảo T. Hiện tại, [expr.type.conv]/1 cho biết rằng giá trị này tạo ra một giá trị theo loại T, điều này là vô nghĩa đối với các loại tham chiếu. Đây là core issue 1521.
  • Điều lành mạnh có lẽ là để có T{x} để tham khảo loại T làm khoảng T __tmp{x}; và sau đó mang lại tương đương với static_cast<T>(__tmp) (vì vậy Xvalue để tham khảo rvalue T và giá trị trái để tham khảo giá trị trái T). Tuy nhiên, C++ 11 đã được công bố đã sửa đổi đặc tả cho việc khởi tạo danh sách các tham chiếu, làm cho nó luôn tạo ra một tạm thời. Kết quả là không thể biên dịch int i; int &r{i}; vì nó sẽ cố gắng ràng buộc r vào bản sao tạm thời i, điều này rõ ràng là vô nghĩa. Điều này được cố định bởi core issue 1288, có độ phân giải GCC được cho là thực hiện, nhưng có vẻ như từ thông báo lỗi rằng nó không hoàn toàn cố định.
Các vấn đề liên quan