2016-05-20 24 views
10

Thuật toán chuẩn minmax có thể được so sánh với một giá trị duy nhất. Tuy nhiên, giá trị trả về minmax thuật toán không thể được so sánh với một cặp giá trị:So sánh tiêu chuẩn :: minmax với một cặp

#include <algorithm> 
#include <utility> 

template<class T1, class T2> 
constexpr auto make_cref_pair(T1&& t1, T2&& t2) 
{ 
    return std::pair<T1 const&, T2 const&>(std::forward<T1>(t1), std::forward<T2>(t2)); 
} 

int main() 
{ 
    static_assert(std::min(2, 1) == 1); // OK 
    static_assert(std::max(2, 1) == 2); // OK 
    //static_assert(std::minmax(2, 1) == std::make_pair(1, 2)); // ERROR, const int& vs int pair comparison 
    static_assert(std::minmax(2, 1) == std::pair<const int&, const int&>(1, 2)); // OK 
    static_assert(std::minmax(2, 1) == make_cref_pair(1, 2)); // OK 
} 

Live Example

Lý do là make_pair(2, 1) trả về một pair<int, int>minmax(1, 2) lợi nhuận một pair<const int&, const int&>. Không có sự quá tải trộn operator== cho pair.

Sửa chữa sau đó để viết rõ ràng std::pair<const int&, const int&>(int, int) hoặc để bọc nội dung này trong một chức năng do nhà sản xuất thực hiện make_cref_pair.

Câu hỏi: có cách nào sạch hơn để so sánh giá trị trả lại minmax với giá trị pair không? Và tôi đã xử lý chính xác các tham chiếu trong số make_cref_pair của tôi?

+1

tôi sợ rằng 'make_cref_pair' có thể không hợp pháp (phần mở rộng thời gian cuộc sống không áp dụng cho các đối tượng con, AFAIK) – sehe

+0

@sehe yikes. Liệu điều tương tự cũng áp dụng cho cặp 'thường' (1,2) '? – TemplateRex

+0

Nó sẽ giống nhau. Tôi không thực sự chắc chắn về điều này, nhưng nó có vẻ như chơi trên các cạnh có – sehe

Trả lời

11

std::minmax có quá tải initializer_list. Này trả về một cặp non-const phi tham khảo:

static_assert(std::minmax({2, 1}) == std::make_pair(1, 2)); 

Thật không may này có thể ít performant, vì sự phức tạp tương ứng là "chính xác một so sánh" và "tại hầu hết các ứng dụng của (3/2) * t.size() vị tương ứng".

+0

tốt, tôi sẽ chỉ sử dụng so sánh tại thời gian biên dịch (nó để khởi tạo một mẫu biến, do đó thẻ C++ 14, tôi cần 'constexpr'). Cảm ơn, đây là một câu trả lời hay! – TemplateRex

+0

bạn có lẽ cũng biết câu trả lời cho các vấn đề suốt đời bằng cách sử dụng 'cặp '? – TemplateRex

+2

@TemplateRex Vấn đề với tham chiếu lơ lửng chỉ là vấn đề nếu bạn cố gắng truy cập 'first' hoặc' second' sau đó. AFAIK đây cũng là một vấn đề với 'minmax'. Cách giải quyết hợp lý là sử dụng 'reference_wrapper'. – user6362820

5

Một điều bạn có thể làm là tận dụng lợi thế của quá tải std::minmax mất std::initializer_list<T> và trả lại std::pair<T,T>. Sử dụng mà bạn có thể có

int main() 
{ 
    const int a = 10, b = 20; 
    static_assert(std::minmax({2, 1}) == std::make_pair(1, 2)); 
    static_assert(std::minmax({a, b}) == std::make_pair(a, b)); 
} 

nào will compile và cho phép bạn để thoát khỏi make_cref_pair. Nó gọi std::minmax_element vì vậy tôi không chắc liệu điều này có làm giảm hiệu quả hay không.

3

Một lựa chọn là để chuyển đổi một cách rõ ràng phía bên tay trái để std::pair<int,int>:

#include <algorithm> 
#include <utility> 

template <typename T1, typename T2> 
constexpr std::pair<T1,T2> myminmax(const T1& t1, const T2& t2) 
{ 
    return std::minmax(t1,t2); 
} 

int main() 
{ 
    static_assert(myminmax(2, 1) == std::make_pair(1, 2)); 
} 
+0

dấu ngoặc đơn của trình khởi tạo là cách thuận tiện hơn để đạt được điều này – TemplateRex

+0

Biến thể nào phù hợp nhất với bạn. Tùy ban :) – mindriot

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