2015-12-29 16 views
16

Hãy xem xét các lớp sau đây:Ít hơn toán tử thông qua chuyển đổi ngầm?

struct C 
{ 
    /* Class contents, without any arithmetic operator... */ 
    constexpr operator int() noexcept; // Implicit conversion to int 
}; 

Câu hỏi của tôi là:

  • là C có thể sử dụng trong thuật toán tiêu chuẩn như std::sort rằng hiện đang sử dụng các nhà điều hành mặc định <?
  • C có được coi là thỏa mãn ý tưởng LessThanComparable không?
  • C sẽ đáp ứng các yêu cầu của thư viện thuật toán giả định được mô tả giả định sẽ yêu cầu loại là LessThanComparable.
+1

Tôi đã tò mò và thử nó. Làm việc trên C++ 14 ở đây: http://cpp.sh/4hdh –

Trả lời

12

C có thể sử dụng trong thuật toán tiêu chuẩn như std::sort rằng hiện đang sử dụng mặc định < điều hành?

Có, nó hoạt động cho std::sort() và một số thuật toán chuẩn khác. Mã số

#include <algorithm> 
#include <vector> 

struct C 
{ 
    /* Class contents, without any arithmetic operator... */ 
    constexpr operator int() noexcept {return 0;} // Implicit conversion to int 
}; 

int main() 
{ 
    std::vector<C> v; 
    std::sort(begin(v), end(v)); 
} 

biên dịch. Here's a live demo. Hãy nhìn vào câu hỏi tiếp theo!

C được coi là đáp ứng ý tưởng LessThanComparable?

số Các yêu cầu của các khái niệm LessThanComparable là, rằng các đối tượng xy loại C hoặc const C biểu thức x<y là hợp lệ và mặc nhiên chuyển đổi thành bool và các nhà điều hành < thiết lập một mối quan hệ đặt hàng yếu nghiêm ngặt. Trong trường hợp của bạn, các đối tượng const sẽ không chuyển đổi thành int s. Đây là một lỗi trong mã của bạn, bởi vì nó không phải là const đúng. Việc thêm từ khóa const sẽ làm cho từ khóa hoạt động và lớp học C thực sự sẽ là LessThanComparable. Mối quan hệ đặt hàng yếu kém nghiêm ngặt được đáp ứng, bởi vì int s thực hiện yêu cầu này.

sẽ C đáp ứng các yêu cầu của một conceptified thư viện thuật toán giả thuyết rằng sẽ yêu cầu các loại được LessThanComparable.

Nếu bạn sửa chữa constness của bạn, có, nó sẽ.

Một vài sidenotes:

  • GCC 4.9 biên dịch x<y ngay cả khi xy là loại const C. Điều này có vẻ là một lỗi trình biên dịch, kể từ GCC 5.2 và clang 3.6 ném một lỗi thời gian biên dịch ở đây.

  • Chuyển std::less<C>() làm đối số bổ sung cho std::sort() đưa ra lỗi thời gian biên dịch, vì hàm so sánh yêu cầu đối tượng không đổi có thể so sánh được trong trường hợp đó. Tuy nhiên, việc đi qua std::less<void>() không làm hỏng bất kỳ điều gì, vì các đối số được chuyển tiếp hoàn hảo.

  • std::sort() algorithm không yêu cầu đầy đủ LessThanComparable, nhưng khái niệm Compare. Hơn nữa, loại trình vòng lặp phải là RandomAccessIteratorValueSwappable và loại tham chiếu phải là MoveContructableMoveAssignable. Đây là tất cả các trường hợp cho câu hỏi đầu tiên của bạn, ngay cả khi lỗi constness không cố định. Đó là lý do tại sao std::sort() và các thuật toán chuẩn khác hoạt động.

+1

Về điểm đầu tiên: thực tế là mã biên dịch và hoạt động trong thực tế không ngụ ý rằng hành vi đó được bắt buộc theo tiêu chuẩn. – chi

+1

@chi Tôi đồng ý. Đó là lý do tại sao thêm một sidenote ở phần cuối của câu trả lời của tôi. Tôi tin rằng tất cả việc triển khai chính xác tiêu chuẩn phải biên dịch mã đã cho. –

3

No. Trình biên dịch không thể thực hiện phép thuật lớn như vậy, tức là gọi phương thức truyền và sau đó áp dụng toán tử <. Hãy tưởng tượng có một số toán tử cast cho các kiểu khác nhau, trình biên dịch sẽ chọn trình thích hợp như thế nào?

EDIT: Thực ra nó không chính xác. Miễn là có một nhà điều hành diễn viên duy nhất, điều này sẽ làm việc. Nhưng với hai hoặc nhiều trình biên dịch sẽ phàn nàn về diễn viên không rõ ràng. Tuy nhiên, cách tiếp cận này rất dễ vỡ nên nói chung không phải là ý hay.

+2

Tôi không thể đồng ý với bạn, cũng không hoàn toàn. Trình biên dịch sẽ gọi diễn viên trước khi áp dụng toán tử. Điều đó sẽ xảy ra bởi vì toán tử là "chỉ là một hàm" và nếu đối tượng đã định nghĩa phương thức đúc hoặc hàm tạo ngầm với một đối số, nó sẽ được đúc để khớp với toán tử này. Sự mơ hồ của một số nhà điều hành diễn viên là một chủ đề hoàn toàn khác. – Glapa

+0

@Glapa: Bạn nói đúng, tôi đã kiểm tra và nó hoạt động. Miễn là tôi chưa thêm một nhà điều hành diễn viên khác. Tôi cập nhật câu trả lời mặc dù. –

+0

Upvote cho chỉnh sửa của bạn. – ildjarn

2

Tôi đã thử ví dụ được đề xuất bởi mehrdad momeny. Nó hoạt động tốt. Tuy nhiên, với ít chỉnh sửa, nó không hoạt động nữa.

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 

struct C 
{ 
    C(int x):X(x){} 
    operator int() { return X; } 
    operator float() { return static_cast<float>(X); } 

    int X; 
}; 

using namespace std; 

int main() 
{ 
    vector<C> u = {1, 2, 35, 6, 3, 7, 8, 9, 10}; 
    sort(u.begin(), u.end()); 
    for(auto x: u){ 
     cout << x << endl; 
    } 
} 

Live Demo

Bởi vì điều này sẽ dẫn đến một sự mơ hồ. Vì vậy, nó không phải là một ý tưởng tốt để làm điều đó như thế này.

+0

Vì vậy, nó có được đảm bảo hoạt động nếu chỉ có một toán tử chuyển đổi không? – user2079303

+0

Tôi không có một đầu mối cho điều đó hơn là ví dụ về mehrdad momeny. Bạn nên đào sâu vào tiêu chuẩn –

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