Tôi đã xác định loại hoạt động như một số nguyên. Tôi muốn xác định một chuyên môn cho std :: common_type cho loại của tôi. Tuy nhiên, chuyên môn này sẽ có thể cung cấp cho common_type của bounded_integer (lớp của tôi) kết hợp với bất kỳ số đối số nào khác là các loại số nguyên bounded_integer hoặc tích hợp khác. Tôi muốn mã sau đây có hiệu lực:Chuyên môn từng phần của mẫu lớp cho một loại xuất hiện ở bất kỳ vị trí nào của gói tham số mẫu variadic
std::common_type<bounded_integer<1, 10>>::type
std::common_type<bounded_integer<1, 10>, int>::type
std::common_type<int, long, bounded_integer<1, 10>>::type
std::common_type<int, int, long, short, long long, short, bounded_integer<1, 10>, int, short, short, short, ..., short, bounded_integer<1, 10>>::type
Lần đầu tiên tôi giải quyết vấn đề này là sử dụng enable_if. Tuy nhiên, tôi nhận ra rằng điều này sẽ không cho phép tôi để phân biệt từ định nghĩa thư viện của common_type, như những gì tôi đã có được chủ yếu
#include <type_traits>
class C {};
template<typename T, typename... Ts>
class contains_c {
public:
static constexpr bool value = contains_c<T>::value or contains_c<Ts...>::value;
};
template<typename T>
class contains_c<T> {
public:
static constexpr bool value = std::is_same<T, C>::value;
};
namespace std {
template<typename... Args, typename std::enable_if<contains_c<Args...>::value>::type>
class common_type<Args...> {
public:
using type = C;
};
} // namespace std
int main() {
}
Trường hợp 'đặc tả từng phần' thực sự chỉ là "bất kỳ đối số", nay đã không còn chuyên môn hơn những gì chúng tôi có.
Vì vậy, nó có vẻ như là giải pháp duy nhất là để yêu cầu người dùng của tôi để làm một trong các cách sau:
- luôn đặt bounded_integer như là đối số đầu tiên common_type
- luôn luôn sử dụng make_bounded của tôi (built-in giá trị số nguyên) để chuyển đổi các số nguyên của chúng thành bounded_integer (vì vậy không có chuyên môn của common_type cho các kiểu dựng sẵn kết hợp với bounded_integer)
- không bao giờ đặt bounded_integer ở vị trí lớn hơn N, trong đó N là một số tôi xác định , tương tự như mẫu Phiên bản cũ của Visual Studio làm việc xung quanh
3 sẽ giống như thế này:
// all_bounded_integer_or_integral and all_are_integral defined elsewhere with obvious definitions
template<intmax_t minimum, intmax_t maximum, typename... Ts, typename = type std::enable_if<all_bounded_integer_or_integral<Ts...>::value>::type>
class common_type<bounded_integer<minimum, maximum>, Ts...> {
};
template<typename T1, intmax_t minimum, intmax_t maximum, typename... Ts, typename = typename std::enable_if<all_are_integral<T1>::value>::type, typename = typename std::enable_if<all_bounded_integer_or_builtin<Ts...>::value>::type>
class common_type<T1, bounded_integer<minimum, maximum>, Ts...> {
};
template<typename T1, typename T2, intmax_t minimum, intmax_t maximum, typename... Ts, typename = typename std::enable_if<all_are_integral<T1, T2>::value>::type, typename = typename std::enable_if<all_bounded_integer_or_builtin<Ts...>::value>::type>
class common_type<T1, T2, bounded_integer<minimum, maximum>, Ts...> {
};
// etc.
Có cách nào tốt hơn để thực hiện điều này (mẫu chuyên môn khi tất cả các loại đáp ứng một điều kiện và bất kỳ các loại đáp ứng điều kiện khác) cho một lớp rằng tôi không thể thay đổi định nghĩa ban đầu cho?
EDIT:
Dựa trên câu trả lời, tôi không đủ rõ ràng trong vấn đề của mình.
Thứ nhất, hành vi mong đợi:
Nếu ai đó gọi std :: common_type với tất cả các loại là một thể hiện của bounded_integer hoặc một built-in kiểu số, tôi muốn kết quả là một bounded_integer rằng có tối thiểu của tất cả các mức tối thiểu có thể và tối đa tất cả các mức tối đa có thể.
Vấn đề:
Tôi có một giải pháp làm việc khi có người gọi std :: common_type trên bất kỳ số lượng bounded_integer. Tuy nhiên, nếu tôi chỉ chuyên phiên bản hai cãi nhau, sau đó tôi chạy vào vấn đề sau đây:
std::common_type<int, unsigned, bounded_integer<0, std::numeric_limits<unsigned>::max() + 1>
nên cho tôi
bounded_integer<std::numeric_limits<int>::min(), std::numeric_limits<unsigned>::max() + 1>
Tuy nhiên, nó không.Trước tiên, nó áp dụng common_type cho int
và unsigned
, tuân theo quy tắc quảng cáo tích phân tiêu chuẩn, cho số unsigned
. Sau đó nó sẽ trả về kết quả của common_type
với unsigned
và bounded_integer
của tôi, cho
bounded_integer<0, std::numeric_limits<unsigned>::max() + 1>
Vì vậy, bằng cách thêm unsigned
đến giữa các gói thông số, mặc dù nó nên hoàn toàn không có tác động vào loại kết quả (dãy của nó hoàn toàn nằm trong phạm vi của tất cả các loại khác), nó vẫn ảnh hưởng đến kết quả. Cách duy nhất tôi có thể nghĩ ra để ngăn chặn điều này là chuyên biệt std::common_type
cho bất kỳ số nào được tích hợp sẵn trong số nguyên theo sau là bounded_integer
, theo sau là bất kỳ số nào được tích hợp sẵn hoặc số nguyên bounded_integer
.
Câu hỏi của tôi là: làm cách nào tôi có thể thực hiện việc này mà không cần phải xấp xỉ bằng cách viết một số tham số tùy ý theo sau là bounded_integer
theo sau là gói tham số hoặc điều này là không thể?
EDIT 2:
Lý do mà common_type sẽ cung cấp cho các giá trị sai có thể được giải thích bằng lý luận này sau khi tiêu chuẩn (trích dẫn từ N3337)
Các common_type
của int
và unsigned
là unsigned
. Ví dụ: http://ideone.com/9IxKIW. Standardese có thể được tìm thấy trong § 20.9.7.6/3, nơi common_type
trong hai giá trị là
typedef decltype(true ? declval<T>() : declval<U>()) type;
Trong § 5,16/6, nó nói
Các toán hạng thứ hai và thứ ba có số học hay loại đếm; các chuyển đổi số học thông thường được thực hiện để đưa chúng vào loại phổ biến và kết quả là loại đó.
Quá trình chuyển đổi số học thông thường được định nghĩa trong § 5/9 như
Ngược lại, nếu các toán hạng có kiểu dữ liệu integer unsigned có rank lớn hơn hoặc tương đương với cấp bậc của các loại khác toán hạng, toán hạng có loại số nguyên đã ký được chuyển đổi thành loại toán hạng có loại số nguyên không dấu.
điều gì nên 'std :: common_type, ngắn> :: loại' đầu ra? 'short' hoặc' ranged_integer :: min(), std :: numeric_limits :: max()> '. –
brunocodutra
@brunocodutra: Tôi đã cập nhật bài đăng của mình để giải thích. Tôi mong đợi kết quả của 'common_type' của bất kỳ biểu thức nào chứa tất cả' ranged_integer' và các kiểu tách rời là một 'ranged_integer' với một phạm vi chứa tất cả các giá trị có thể có từ bất kỳ kiểu nào. –