2012-09-25 24 views
6

Tại thời gian biên dịch trong C++ 11 trong một hàm mẫu có 2 tham số mẫu, cả hai đều là các kiểu số nguyên không dấu, tôi muốn có một biến cục bộ có kiểu của bất kỳ tham số mẫu nào có nhiều bit. Trong C++ 03 Tôi có thể viết một cái gì đó như:C++ 11 cách viết mẫu để chọn loại số nguyên lớn hơn?

template<bool, class T, class U> 
struct pick_first; 

template<class T, class U> 
struct pick_first<true, T, U> { 
    typedef T type; 
}; 

template<class T, class U> 
struct pick_first<false, T, U> { 
    typedef U type; 
}; 

template<class T, class U> 
struct pick_bigger { 
    typedef typename pick_first<(sizeof(T) >= sizeof(U)), T, U>::type type; 
}; 

// usage 
template<class uintX_t, class uintY_t> 
void foo() { 
    typename pick_bigger<uintX_t, uintY_t>::type mylocal = 0; 
    // insert doing stuff with mylocal here 
} 

Tôi có thể tận dụng bất kỳ tính năng C++ 11 mới nào để đơn giản hơn không? Tôi biết tôi có thể sử dụng các mẫu variadic để làm cho nó hoạt động với nhiều hơn chỉ là các cặp, và thay vì sử dụng pick_first tôi có thể viết rất nhiều chuyên môn để làm cho nó hoạt động với các kiểu int_leastX_t và int_fastX_t mới. Nhưng tôi tò mò nếu có một cách tiếp cận đơn giản hơn cho điều này. Có lẽ bằng cách nào đó tận dụng auto/constexpr/decltype?

+4

Bạn đã xem 'std :: common_type' –

+0

Tôi chưa từng nghe nói về std :: common_type! Rất thú vị. Điều này sẽ làm việc cho tôi. Bạn nên đăng bài như một câu trả lời mặc dù vậy tôi có thể bỏ phiếu cho bạn;) –

+0

@ DavidRodríguez-dribeas Nhưng 'common_type' sẽ không phải lúc nào cũng hoạt động do các quy tắc khuyến mãi số nguyên. Ví dụ: 'std :: common_type :: type' là' int', có thể lớn hơn một trong hai loại. – Praetorian

Trả lời

7

pick_first của bạn chỉ là std :: có điều kiện trong C++ 11, vì vậy bạn có thể viết

template<class T, class U> 
struct wider { 
    using type = typename std::conditional<sizeof(T) >= sizeof(U), T, U>::type; // I'm using the C++11 type alias feature 1) to educate people about them and 2) because I like them better than typedefs. 
}; 

Nếu bạn chỉ muốn một kiểu phù hợp để giữ kết quả của một số biểu hiện liên quan đến cả hai loại và không nhất thiết cần phải chính xác một trong hai loại sau đó std::common_type, hoặc có lẽ auto, là giải pháp tốt nhất:

template<class uintX_t, class uintY_t> 
void foo() { 
    typename std::common_type<uintX_t, uintY_t>::type mylocal = 0; 
    // insert doing stuff with mylocal here 
} 

// or 
template<class uintX_t, class uintY_t> 
void foo(uintX_t x, uintY_t y) { 
    auto mylocal = x + y; 
} 

và thực hiện lại pick_bigger thiếu typename trong đó: 012.

+0

Điều này thêm ma thuật mẫu phức tạp, với mã không biên dịch với trình biên dịch được sử dụng nhiều nhất, để tạo ra một kiểu tối ưu phụ cho biến cục bộ mà OP muốn một kiểu cho. Điều đó cực kỳ ngớ ngẩn. Nhưng nó trông rất thông minh. –

+0

Wow, đã không nhận thức được std :: có điều kiện hoặc là, ngọt ngào. –

+0

@JosephGarvin Bạn có thể xem http://en.cppreference.com/w/cpp/types để xem tất cả các đặc điểm kiểu mới. – bames53

1

vì cả hai loại đều không được ký, chỉ cần thực hiện decltype(T1() + T2()).

+5

Điều này có cùng vấn đề với khuyến mãi số nguyên như common_type, decltype (char() + short()) là int. Nếu đó là chấp nhận được thì chỉ cần sử dụng common_type trực tiếp là giải pháp tốt nhất. – bames53

+0

@ barnes54: common_type thêm phụ thuộc tiêu đề. không cần thiết cho điều đó. như để nhận 'unsigned int' thay vì' short', OP yêu cầu một kiểu phù hợp cho biến cục bộ. loại phù hợp nhất là loại có thể lưu trữ kết quả biểu hiện trực tiếp mà không cần chuyển đổi. đó là những gì biểu thức này tạo ra. và rằng loại phù hợp nhất không phải là những gì một bộ chọn templated chế tạo quá ngớ ngẩn tạo ra. –

+0

@downvoter: vui lòng giải thích câu trả lời của bạn. tôi biết, lời giải thích sẽ * âm thanh * hợp lý, cũng giống như bình luận upvoted ba lần của barnes53, và tôi có lẽ thậm chí không bình luận về nó (đã được thảo luận). nhưng chỉ để hoàn thành. –

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