2010-10-26 30 views
5

Nếu tôi tạo thành một thành viên trỏ đến cơ sở, tôi có thể chuyển đổi thành thành viên con trỏ đến thành phần thường, nhưng không được sử dụng trong mẫu như Buzz bên dưới, nơi đối số mẫu đầu tiên ảnh hưởng đến đối số thứ hai. Tôi có đang chiến đấu với lỗi trình biên dịch hay không tiêu chuẩn thực sự ủy nhiệm điều này không hoạt động?Tại sao tôi không thể chuyển con trỏ xuống thành viên trong đối số mẫu?

struct Foo 
{ 
    int x; 
}; 

struct Bar : public Foo 
{ 
}; 

template<class T, int T::* z> 
struct Buzz 
{ 
}; 

static int Bar::* const workaround = &Foo::x; 

int main() 
{ 
    // This works. Downcasting of pointer to members in general is fine. 
    int Bar::* y = &Foo::x; 

    // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not? 
    // Error: could not convert template argument '&Foo::x' to 'int Bar::*' 
    Buzz<Bar, &Foo::x> test; 

    // Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in 
    // a constant expression 
    Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test; 

    // Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot 
    // appear in a constant expression" 
    Buzz<Bar, workaround> test; 

    return 0; 
} 

Trả lời

5

Đơn giản là không được phép. Theo §14.3.2/5:

Các chuyển đổi sau đây được thực hiện trên mỗi biểu thức được sử dụng làm đối số mẫu không kiểu. Nếu một đối số mẫu không kiểu không thể được chuyển đổi thành kiểu của tham số mẫu tương ứng thì chương trình đó không đúng định dạng.
- đối với một tham số mẫu không kiểu của kiểu tích phân hoặc liệt kê, các khuyến mãi tích phân (4.5) và chuyển đổi tích phân (4.7) được áp dụng.
- cho một tham số mẫu không kiểu của con trỏ kiểu tới đối tượng, chuyển đổi tiêu chuẩn (4.4) và chuyển đổi mảng-thành-con trỏ (4.2) được áp dụng. - Đối với tham số mẫu không phải kiểu tham chiếu kiểu đối tượng, không có chuyển đổi nào được áp dụng. Loại được tham chiếu bởi tham chiếu có thể có độ phân giải cao hơn loại đối số mẫu (nếu không giống hệt). Tham số mẫu được gắn trực tiếp với đối số mẫu, mà phải là một giá trị.
- Đối với một tham số mẫu không kiểu của con trỏ kiểu để hoạt động, chỉ áp dụng chuyển đổi hàm-điểm-con trỏ (4.3). Nếu đối số mẫu đại diện cho một tập hợp các hàm bị quá tải (hoặc một con trỏ đến đó), hàm kết hợp được chọn từ tập hợp (13.4).
- Đối với một tham số mẫu không kiểu tham chiếu kiểu hàm, không có chuyển đổi nào được áp dụng. Nếu đối số mẫu đại diện cho một tập hợp các hàm bị quá tải, hàm kết hợp được chọn từ tập hợp (13.4).
- Đối với một tham số mẫu không phải kiểu của con trỏ loại thành hàm thành viên, không có chuyển đổi nào được áp dụng. Nếu đối số mẫu đại diện cho một tập hợp các hàm thành viên quá tải, hàm thành viên phù hợp được chọn từ tập hợp (13.4).
- Đối với một tham số mẫu không kiểu của con trỏ kiểu cho thành viên dữ liệu, chuyển đổi đủ điều kiện (4.4) được áp dụng.

Tôi đã nhấn mạnh chuyển đổi liên quan đến con trỏ đến thành viên dữ liệu. Lưu ý rằng chuyển đổi của bạn (§4.11/2) không được liệt kê. Trong C++ 0x, nó vẫn giữ nguyên trong vấn đề này.

+0

Chắc chắn đúng, nhưng bất kỳ ý tưởng nào tại sao nó không được phép? Có vẻ tùy ý. –

+1

@ Joseph: Tôi nghĩ nó cũng vậy, đó là lý do tại sao tôi cũng kiểm tra C++ 0x. (Họ đã xóa nhiều quyết định dường như tùy tiện, như không có tham số mẫu mặc định cho mẫu chức năng.) Không ai tìm thấy cách sử dụng cho nó và do đó nó không thực sự thay đổi/vì vậy nó không được đẩy (dễ dàng hơn để thêm giếng) tính năng thử nghiệm hơn là không dùng tính năng bị hỏng) hoặc có một số lý do cơ bản mà tôi không thể thấy. – GManNickG

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