2013-03-23 33 views
13

Tôi đang viết một bí danh mẫu quảng cáo tương tự như boost :: promotion nhưng for C++ 11. Mục đích của việc này là để tránh cảnh báo khi truy xuất đối số từ các hàm đa dạng. ví dụ.C++ 11 loại đặc điểm để phân biệt giữa lớp enum và enum thường xuyên

template <typename T> 
std::vector<T> MakeArgVectorV(int aArgCount, va_list aArgList) 
{ 
    std::vector<T> args; 
    while (aArgCount > 0) 
    { 
     args.push_back(static_cast<T>(va_arg(aArgList, Promote<T>))); 
     --aArgCount; 
    } 
    return args; 
} 

Các Thúc đẩy mẫu alias thúc đẩy các loại hình sau việc thúc đẩy đối số mặc định cho các đối số variadic: 1) Một số nguyên đó là nhỏ hơn một int được thăng int 2) Một float được đề bạt lên gấp đôi

Vấn đề của tôi là một enum chuẩn C++ có thể được quảng bá nhưng một lớp enum C++ 11 không được phát huy (trình biên dịch không tạo ra một cảnh báo). Tôi muốn quảng bá để làm việc với một enum thường xuyên nhưng bỏ qua một lớp enum C++ 11.

Làm cách nào để biết sự khác biệt giữa một lớp enum và enum trong bí danh mẫu Quảng bá của tôi?

+1

Vấn đề thực sự là bạn đang sử dụng 'va_arg' thay vì mẫu' std :: initializer_list' và/hoặc variadic. – Fanael

+0

Cảm ơn mẹo nhưng tôi có va_list vì tôi đang làm việc với giao diện C. – Sam

+0

@Sam: Câu trả lời của tôi có giải quyết được vấn đề của bạn không? –

Trả lời

21

Đây là một giải pháp khả thi:

#include <type_traits> 

template<typename E> 
using is_scoped_enum = std::integral_constant< 
    bool, 
    std::is_enum<E>::value && !std::is_convertible<E, int>::value>; 

Các giải pháp khai thác sự khác biệt trong hành vi giữa scoped và enumerations unscoped quy định tại Khoản 7.2/9 của C++ 11 Tiêu chuẩn:

Các giá trị của một điều tra viên hoặc một đối tượng của một kiểu liệt kê chưa được điều chỉnh được chuyển đổi thành một số nguyên bằng cách thúc đẩy tích phân (4.5). [...] Lưu ý rằng hàm enum ngầm định này không được cung cấp cho một kiểu liệt kê. [...]

Dưới đây là một minh chứng về cách bạn sẽ sử dụng nó:

Và đây là một live example.

LỜI CẢM ƠN:

Nhờ Daniel Frey đã chỉ ra rằng cách tiếp cận trước đây của tôi sẽ chỉ làm việc miễn là không có tình trạng quá tải do người dùng định nghĩa của operator +.

+3

+1, nhưng có một hang động tại: Nó chỉ hoạt động miễn là tác giả của một số lớp enum 'E' có ** không ** định nghĩa toán tử' của riêng mình + (int, E) '. Sửa chữa nó bằng cách thêm một 'void dummy (int)' và sử dụng 'decltype (dummy (std :: declval ()))'. –

+1

@DanielFrey: Tốt. Trên thực tế tôi có thể sử dụng toán tử khác, chẳng hạn như '^', để làm cho nó ít có khả năng gây trở ngại cho quá tải toán tử do người dùng định nghĩa –

+1

@AndyProwl: hoặc gọi hàm có 'int'. – Fanael

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