2014-06-30 33 views
11

Các công việc sau tốt (như mong đợi):Template chuyển đổi sang const tham chiếu

struct X {}; 

struct A 
{ 
    operator X const&() 
    { 
    static const X value{}; 
    return value; 
    } 
}; 

int main() 
{ 
    A a; 
    X x = a; 
} 

Nhưng điều này không phải là quá rõ ràng:

template<typename T> 
struct X {}; 

struct A 
{ 
    template<typename T> 
    operator X<T> const&() 
    { 
    static const X<T> value{}; 
    return value; 
    } 
}; 

int main() 
{ 
    A a; 
    X<int> x = a; 
} 

GCC 4.9 nói error: conversion from ‘A’ to non-scalar type ‘X<int>’ requested trong khi kêu vang 3,4 có không có vấn đề với nó. Nếu bạn xóa const hoặc & khỏi chức năng chuyển đổi hoặc nếu bạn viết X<int> const &x = a thì GCC cũng vui.

Vì vậy GCC chỉ không tìm thấy hàm chuyển đổi nếu loại mục tiêu là const & đối với lớp mẫu và bạn yêu cầu chuyển đổi thành đối tượng không phải const & của lớp đó. Đây có phải là hành vi đúng không? Tôi đã cố gắng để đọc tiêu chuẩn nhưng các quy tắc quá tải khá khó hiểu với tôi.

Trả lời

5

Có, đây là lỗi trong gcc. Đây là gần như chính xác core DR976, sự khác biệt duy nhất là trong ví dụ của họ loại đích là một loại phi lớp:

struct F { 
    template<class T> 
    operator const T&() { static T t; return t; } 
}; 

int main() { 
    F f; 
    int i = f; // ill-formed 
} 

Như với ví dụ của bạn, kêu vang chấp nhận và gcc từ chối ví dụ này, không phụ thuộc vào phiên bản tiêu chuẩn phương ngữ đã chọn.

Lưu ý rằng điều khoản được sửa đổi bởi DR đó (14.8.2.3 [temp.deduct.conv]) không phân biệt giữa loại lớp và loại không phải lớp, do đó độ phân giải của DR đó áp dụng cho mã của bạn như nhau.

mỗi mệnh đề sửa đổi 14.8.2.3, trình biên dịch nên:

  • xác định P, kiểu trả về của hàm chuyển đổi mẫu, như X<T> const &, và A, loại kết quả yêu cầu, như X<int>;
  • tách tham chiếu từ P, cho số X<T> const;
  • tước tiêu chuẩn cv từ P, tặng X<T>;
  • suy ra Tint.

Tôi khuyên bạn nên gửi báo cáo lỗi về số https://gcc.gnu.org/bugzilla/ tham chiếu đến DR đó.


Bởi vì trong trường hợp của bạn, bạn đang chuyển đổi sang một kiểu lớp, có một cách giải quyết có sẵn:

X<int> x1 = a;   // fails 
X<int> x2(a);   // OK 
X<int> x3 = X<int>(a); // also OK 

Trong trực khởi, nhà thầu của các loại địa điểm được coi là (8.5p16); hàm tạo bản sao mặc định của X<int> có tham số loại X<int> const&, mà chúng tôi đã thấy gcc rất vui khi chuyển đổi a.

+0

Nhờ lời giải thích tuyệt vời của bạn và liên kết đến báo cáo lỗi tôi đã gửi báo cáo lỗi: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61663 –

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