Đây là một cách tiếp cận chung – một TMP cho gấp nhị phân, sử dụng C++ 14. Trước tiên, hãy xác định các hoạt động kết hợp cơ bản:
#include <type_traits>
struct and_op
{
using type = bool;
using identity = std::true_type;
template <bool A, bool B> static constexpr bool value = A && B;
};
struct or_op
{
using type = bool;
using identity = std::false_type;
template <bool A, bool B> static constexpr bool value = A || B;
};
Bây giờ thực tế fold
cơ khí:
template <typename Op, typename Op::type...>
struct fold;
template <typename Op>
struct fold<Op> : Op::identity {};
template <typename Op, typename Op::type Val>
struct fold<Op, Val>
: std::integral_constant<typename Op::type
, Val> {};
template <typename Op, typename Op::type Val, typename Op::type... Tail>
struct fold<Op, Val, Tail...>
: std::integral_constant<typename Op::type
, Op::template value<Val, fold<Op, Tail...>::value>> {};
Tiếp theo, chúng ta cần một cách để tạo ra những đặc điểm unary từ những đặc điểm nhị phân bằng cách liên kết:
template <template <typename, typename> class BPred, typename T>
struct bind_pred
{
template <typename U>
struct pred_1st : std::integral_constant<bool, BPred<T, U>::value> {};
template <typename U>
struct pred_2nd : std::integral_constant<bool, BPred<U, T>::value> {};
};
Cuối cùng, một trình bao bọc trợ giúp để kết hợp kết quả của việc áp dụng biến vị ngữ đơn nhất:
template <typename Op, template <typename> class UPred, typename ...Args>
struct fold_pred : fold<Op, UPred<Args>::value...> {};
Vậy đó. Bây giờ chúng ta hãy làm việc:
template <typename T>
using maybe_double = bind_pred<std::is_convertible, double>::pred_2nd<T>;
#include <iomanip>
#include <iostream>
int main()
{
std::cout
<< std::boolalpha
<< fold_pred<and_op, maybe_double, int, float>::value << '\n'
<< fold_pred<and_op, maybe_double, int, float, void>::value << '\n';
}
Trong C++ 17 (hoặc C++ 1Z, chứ không phải), bạn có thể viết các giải pháp trực tiếp với mã nhờ ít hơn để các biểu thức lần mới. Ví dụ:
template <template <typename> class UPred, typename ...Args>
static constexpr bool pred_all = (UPred<Args>::value && ...);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unary fold
Cách sử dụng:
static_assert(pred_all<maybe_double, int, float>);
Gọn gàng, nhưng không có khái quát hóa rõ ràng về "bất kỳ sự thật nào"? –
@KerrekSB "bất kỳ là đúng" = không "tất cả sai". Vì vậy, chỉ cần xác định 'all_false' theo các dòng tương tự và làm' template bằng cách sử dụng any_true = std :: integral_constant :: value>; ' –
Ah, tất nhiên :-) –