2011-09-09 26 views
5

Có thể và/hoặc hữu ích để xác định operator "" (...) làm chức năng kết bạn không?C++ 0x, các chữ cái do người dùng xác định với toán tử bạn ""()

class Puzzle { 
    friend Puzzle operator "" _puzzle(const char*, size_t); 
    ... 
}; 
void solve(Puzzle); 
int main() { 
    solve("oxo,xox"_puzzle); 
}; 

Tôi đang nghĩ về "hữu ích" đặc biệt, vì các quy tắc mà operator "" được định nghĩa trong một namespace chỉ - không phải là ít nhất vì định bắt đầu với _ được dành riêng trong không gian tên toàn cầu. Đây có phải là friend vi phạm quy tắc này tại đây không? Vì vậy, sẽ không có lợi ích gì với việc đóng gói không hoàn toàn này, đúng không?

Trả lời

2

Các địa chỉ Tiêu chuẩn này trực tiếp tại địa điểm duy nhất nó đề cập đến bất kỳ hạn chế về khai báo của literals người dùng định nghĩa, §13.5.8/2:

Một tuyên bố có declarator-id là một chữ-điều hành -id sẽ là khai báo hàm hoặc phạm vi chức năng không gian tên (nó có thể là chức năng của bạn bè (11.3)), một cách rõ ràng hoặc chuyên môn hóa một mẫu chức năng hoặc khai báo sử dụng (7.3.3).

Nếu bạn bè cũng được khai báo ở phạm vi không gian tên, thì không có sự phân biệt giữa định nghĩa trong phạm vi lớp hoặc không gian tên. Lưu ý rằng không có yêu cầu về định nghĩa ở phạm vi không gian tên, mà câu hỏi của bạn là các lời xác nhận hiện đang diễn đạt.

Nếu không khai báo ở phạm vi không gian tên, vì ADL không thể tìm thấy, bạn bè có thể được sử dụng riêng trong lớp nơi phạm vi của tra cứu tên không đủ tiêu chuẩn. Đây là cách duy nhất để khai báo toán tử theo nghĩa đen chứ không phải là giao diện bên ngoài.

Nếu người bạn được xác định bên trong mẫu lớp, thì hai bản sao của mẫu sẽ tạo ra hai hàm được đặt tên giống nhau ở phạm vi không gian tên, sẽ va chạm ngay cả khi chúng ẩn bên ngoài phạm vi lớp.

+0

Tôi thực sự nghĩ rằng tôi đã đọc nó ở đâu đó, mà hậu tố * nên * chỉ được khai báo bên trong một ** không gian tên **. Tôi không thể nhớ ở đâu - nhưng đó chỉ là một gợi ý, không phải là một yêu cầu. Và do đó, nó có lẽ là một mẹo duy nhất cho "thực hành tốt". Điểm tốt về chức năng người bạn ** mẫu **. Đây không phải là vấn đề với mẫu * friend * thông thường, ít nhất một trong các đối số cho hàm friend là một cá thể lớp - sau đó không có vấn đề đặt tên. – towi

+1

Tôi nhớ nhìn thấy một cái gì đó như thế này trong các giấy tờ vị trí trước đó. Hãy thử n2378.pdf phần 5: Một thành ngữ. Ở đây họ nói: 1. Các chức năng này không được tìm thấy thông qua ADL khi được gọi thông qua các chữ thay vì biểu mẫu toán tử rõ ràng. 2. Điều này sẽ cám dỗ vị trí trong toàn cầu. 3. Điều này sẽ dẫn đến xung đột ngay cả trong mã mà không sử dụng chữ. 4. Vì vậy, đặt các ops chữ trong một không gian tên và đặt một chỉ thị sử dụng để kéo chúng đến mức toàn cầu. – emsr

+0

Tôi chỉ muốn lưu ý rằng bạn có thể * không * sử dụng chức năng bạn bè riêng tư bên trong lớp học, xem [câu hỏi này] (http://stackoverflow.com/questions/8207633/whats-the-scope-of-inline-friend -chức năng). – Xeo

0

Theo tiêu chuẩn, có, tuyên bố kết bạn phải hợp pháp. Nhân tiện, tên này là tốt cho mã người dùng vì nó bắt đầu bằng dấu gạch dưới ngay cả trong không gian tên chung.

Tuyên bố bạn bè sẽ cho phép nhà điều hành truy cập dữ liệu riêng tư của lớp học.

Tôi bắt đầu đặt câu hỏi về tính hữu ích của các nhà khai thác văn học bạn bè. Bởi vì các toán tử do người dùng định nghĩa chỉ có thể có một vài danh sách đối số nên không có cách nào để đưa lớp đó vào các đối số. Vì vậy, bây giờ có cách để tìm kiếm phụ thuộc đối số để tìm đúng chức năng. Tôi có đúng không?

+0

Tôi nghĩ rằng ADL có thể được sử dụng, nhưng nó phải tìm một đối số 'const char *' hoặc bất kỳ toán tử nào của bạn được định nghĩa. Nhưng dù sao, tôi cũng nghi ngờ tính hữu dụng: Ok, bạn có thể truy cập dữ liệu cá nhân, nhưng bạn cần phải gọi một hàm tạo. BTW: johannes (bình luận anwers khác) chỉ ra, rằng tên không phải là '_puzzle', nhưng' nhà điều hành "" _puzzle' và do đó sẽ không bắt đầu với một gạch dưới. – towi

+0

Có, theo 13.5.8/7 tra cứu thường xuyên sẽ chiếm ưu thế cho các nhà khai thác theo nghĩa đen. Tôi gặp vấn đề về tên. Tôi đã bị treo lên trên 17.6.4.3.5 mà dự trữ hậu tố đen * mà không có * một dấu gạch dưới hàng đầu cho việc thực hiện. – emsr

+1

Tôi nghĩ rằng điều chính họ được thiết kế cho là họ sẽ cho phép một thư viện chỉ thực hiện, ví dụ, thập phân. Các toán tử dạng chữ do người dùng định nghĩa cung cấp một cái móc vào trong từ khóa. – emsr

1

Trong trường hợp nó giúp với cú pháp, đây là cách tôi tuyên bố một nhà điều hành literal người bạn người dùng định nghĩa trong một lớp học, nơi mà các nhà điều hành chính nó là trong một không gian tên:

class Integer; 
namespace literals { 
    Integer operator "" _I (const char *); 
} 

// Infinite precision integer 
class Integer { 
    public: 

    // Basic constructor & destructor 
    Integer(); 
    ~Integer(); 

... rest of the interface ... 

    // Literal operator 
    friend Integer literals::operator "" _I (const char *); 

    private: 

    struct Detail; 
    std::unique_ptr<Detail> detail; 

}; 

Người dùng kéo trong điều hành với một using namespace literals; tuyên bố chỉ khi họ muốn. (Và, trên thực tế, tất cả điều này là trong một không gian tên cha mẹ, nhưng bạn có được ý tưởng).