Chỉnh sửa: Tôi đã mắc lỗi đơn giản khi sử dụng SFINAE. Sửa lỗi đó giải quyết lỗi trình biên dịch mà tôi đề cập bên dưới. Tuy nhiên tôi vẫn tò mò về lý do tại sao thông số mẫu không thể được suy ra trong trường hợp này.Tại sao thông số mẫu này không được khấu trừ?
Tôi muốn viết một bản mẫu metaprogram mẫu C++ 14 để tính ước số chung lớn nhất (GCD) của số std::integer_sequence
. Sau khi một số mày mò tôi đến với gần ví dụ hoàn chỉnh này:
template <typename T, T A, T B, T... Ints>
struct GCD<std::integer_sequence<T, A, B, Ints...>> :
GCD<typename std::integer_sequence<T, GCD_pair<T, A, B>::value, Ints...>> {};
template <class T, T A, T B>
struct GCD<std::integer_sequence<T, A, B>> :
GCD_pair<T, A, B> {};
int main() {
using seq = std::integer_sequence<int, 65537, 5, 10>;
cout << GCD<seq>::value << endl;
return 0;
}
Tôi chỉ bóc hai yếu tố đầu tiên của dãy số nguyên, và tìm ra GCD trong số họ sử dụng để được viết GCD_pair
metafunction. Sau đó, tôi áp dụng GCD
cho kết quả của GCD_pair
và các yếu tố còn lại.
Các "rõ ràng" thi hành GCD_pair
không biên dịch:
// This does not work:
// type 'T' of template argument '0' depends on a template parameter
template <typename T, T M, T N>
struct GCD_pair : std::integral_constant<T, GCD_pair<T, N, M % N>::value> {};
template <typename T, T M>
struct GCD_pair<T, M, 0> : std::integral_constant<T, M> {};
Vì vậy, tôi đã cố gắng thực hiện khác có thể sử dụng SFINAE:
// This doesn't work either:
// template parameters not deducible in partial specialization
template <typename T, T M, T N, typename = void>
struct GCD_pair : std::integral_constant<T, M> {};
template <typename T, T M, T N, typename std::enable_if<(M % N != 0)>::type>
struct GCD_pair<T, M, N, void> : std::integral_constant<T, GCD_pair<T, N, M % N>::value> {};
Edit: Tôi đã thực hiện một lỗi. Xem câu trả lời dưới đây để sửa chữa việc sử dụng SFINAE của tôi. Nhưng tôi vẫn tò mò về câu hỏi của tôi:
Tại sao thông số mẫu typename std::enable_if<(M % N != 0)>::type
không được khấu trừ? Nó không được khấu trừ bao giờ về nguyên tắc, hoặc có thể tham số như trong trường hợp này thực sự được suy luận trong thực tế? Nói cách khác, điều này có thể được coi là một giám sát thực hiện trình biên dịch?
Đối với những gì đáng giá, tôi có thể triển khai a slightly different version bằng cách "ẩn" điều kiện (M % N != 0
) có điều kiện trong thông số mẫu bool
. Tuy nhiên, Tôi nghĩ cả hai điều trên là triển khai hợp lý vì operator%
và so sánh với 0
với operator!=
được định nghĩa hoàn hảo cho tất cả các loại tích phân của C++.
Ngoài ra, 'GCD' cần mẫu chính, ví dụ: 'mẫu struct GCD;'. –
Corristo
Chắc chắn rồi! Silly tôi, tôi đã thực hiện một sai lầm đơn giản. – JohnDuck
Vì vậy, tôi nhanh chóng chấp nhận điều này bởi vì bạn đã chỉ ra lỗi của tôi khi sử dụng SFINAE - tuy nhiên tôi đã xem xét lại vì câu hỏi của tôi vẫn đứng vững. Tại sao thông số mẫu không được suy luận? – JohnDuck