2011-01-31 21 views
8

Câu hỏi này rõ ràng cho rằng chúng tôi không muốn sử dụng mẫu cho loại này (vì bất kỳ lý do gì).Có C++ 0x cho phép decltype() trong chữ ký chức năng?

class Product 
{ 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) // 1. 
     : mPrice(price_), mLabel(label_) 
    {} 

    decltype(mPrice) price() const {return mPrice;} // 2. 
    decltype(mLabel) label() const {return mLabel;} // 2. 


private: 

    float mPrice ; // type might later be changed to more acurate floating point abstraction 
    std::string mLabel; // type might later be changed by a special localization-oriented string 
}; 

Câu hỏi đặt ra là: được 1. và 2. cho phép và có thể (hoặc thậm chí đặc biệt được xác định) trong C++ 0x?

Trả lời

7

Tất cả bạn phải làm là tuyên bố mPricemLabeltrước bạn sử dụng decltype:

class Product 
{ 
private: 
    float mPrice ; 
    std::string mLabel; 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) // 1. 
     : mPrice(price_), mLabel(label_) 
    {} 

    decltype(mPrice) price() const {return mPrice;} // 2. 
    decltype(mLabel) label() const {return mLabel;} // 2. 
}; 

này biên dịch tốt dưới g ++ 4.4 với -std = C++ 0x.

Chỉnh sửa Vấn đề là trình biên dịch phải có khả năng phân tích cú pháp khai báo hàm trên thẻ đầu tiên. Phần thân của hàm thành viên có thể được biên dịch sau khi các khai báo thành viên đã được phân tích cú pháp, nhưng bản thân các khai báo thành viên phải được hiểu ngay lập tức - nếu không, trình biên dịch kém bắt đầu ở đâu?

Vì vậy, loại của mọi đối số hàm thành viên phải được biết ngay khi gặp phải.

+0

Tuyệt! Đó là hành vi tiêu chuẩn hay chỉ có hành vi thực hiện gcc? – Klaim

+0

Theo như tôi biết, đây là hành vi tiêu chuẩn. – TonyK

+0

@Klaim Tiêu chuẩn nói "Loại trả về được xác định muộn là hữu ích nhất cho một loại sẽ phức tạp hơn để xác định trước khi khai báo-id" mà dường như chỉ ra rằng đặt decltype trước khi hàm hợp lệ và giá trị trả về là tùy chọn cho các trường hợp dễ dàng hơn (hoặc các lamdas khi cần) – MerickOWA

8

Vâng, nhưng với một cú pháp khác nhau:

auto price() -> decltype(mPrice) { return mPrice; } 
auto price() -> decltype(mPrice) { return mPrice; } 

More chung:

auto function(...) -> decltype(EXPRESSION) ... 

function kiểu trả về sẽ là loại EXPRESSION


EDIT

về trường hợp 1 Tôi không chắc chắn. Tôi không nghĩ rằng là hợp lệ, vì không nghĩ rằng mPrice là một biểu thức hợp lệ trong bối cảnh như vậy: bạn đang sử dụng một thành viên chức năng không tĩnh (Product::mPrime) mà không có một đối tượng.

Đoán của tôi cũng là nếu mPrime là thành viên tĩnh, nó sẽ hoạt động.

+0

Bạn có chắc chắn, tôi đang gặp lỗi biên dịch với g ++ vì các biến không nằm trong phạm vi (có ý nghĩa vì chúng là các biến mẫu). – Motti

+0

Bạn không trả lời cho trường hợp 1. – Klaim

+0

@Kêu cầu: cập nhật câu trả lời của tôi – peoro

1

AFAIK đây là không phải hợp pháp vì các biến mẫu không nằm trong phạm vi tại các điểm bạn sử dụng chúng.

Hãy xem xét điều gì sẽ xảy ra nếu bạn có các biến sau khai báo trước khi lớp học của bạn:

int mPrice; 
char mLabel; 
class Product 
{ /*...*/ }; 

Trong chức năng decleration mPrice sẽ liên kết với các biến toàn cầu chứ không phải là thành viên chẳng hạn.

Cả g ++ 4.5 và VS10 từ chối biên dịch mã của bạn kể từ mPricemLabel nằm ngoài phạm vi.

Tuy nhiên, điều này dường như không phù hợp với thông số mặc định.

int mPrice = 3; 
class Product 
{ // ... 
    int foo(int i = mPrice) { return i; } 
}; 

Product p(5.3, "hi"); 
std::cout << p.foo(); 

này mang lại cho tôi một lỗi biên dịch:

invalid use of non-static data member 'Product::mPrice'

+0

Vâng, tôi không biết, bởi vì decltype() chấp nhận các biểu thức, do đó, điểm là biểu thức không được đánh giá trong trường hợp này, nhưng nó là trong ví dụ của bạn. Vì vậy, những gì tôi yêu cầu là trong trường hợp decltype(), nó sẽ có thể sử dụng các biểu thức hoặc là nó một cách rõ ràng bị cấm? – Klaim

2

vC++ 2010 biên dịch này w/o lỗi:

 

class Product 
{ 
private: 

    float mPrice ; 
    std::string mLabel; 
public: 
    Product(decltype(mPrice) price_, decltype(mLabel) label_) 
     : mPrice(price_), mLabel(label_){} 

    auto price(decltype(mPrice)* p=NULL) const -> decltype(mPrice) {return mPrice;} 

    auto label(decltype(mPrice)* m=NULL) const -> decltype(mLabel) {return mLabel;} 

}; 

nhưng nếu tôi loại bỏ các thông số mặc định giả từ tờ khai phương pháp, lỗi xuất hiện một lần nữa. decltype trong loại trả lại chỉ hoạt động nếu nó cũng xuất hiện trong một số tham số chức năng (???)

(Xin lỗi, tôi hiểu rằng nó phải là nhận xét, nhưng có vẻ thú vị và không thuận tiện để đưa mã vào nhận xét)

+0

Điều này biên dịch tốt dưới g ++ 4.4.0 với -std = C++ 0x, ngay cả sau khi loại bỏ các thông số mặc định giả. Xem http://ideone.com/jGrak để lấy bằng chứng. – TonyK

+0

@TonyK: Tôi gần như không có nghi ngờ rằng gcc nên biên dịch mã này nếu nó biên dịch mã bạn trình bày trong câu trả lời của bạn. Lỗi có lẽ là msvC++ cụ thể, nhưng rất lạ, tuy nhiên. – user396672

+0

Điều thú vị là, dường như nó không quan trọng tham số là gì, chỉ miễn là có một tham số. Tham số có thể chỉ là "giá tự động (int = 0)" và nó vẫn hoạt động. – MerickOWA

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