Talk:cpp/algorithm/all any none of
I notice that the example use member functions v.cbegin and v.cend.
I considered changing to begin(v), end(v), since the free functions are preferred over the members, and it would be nice to establish that as the norm.
On the other hand, there are no non-member cbegin, cend-yet (pre C++14), and perhaps member cbegin/cend are preferable to non-member non-const begin-end?
90.228.215.93 10:12, 15 August 2014 (PDT) Lukas
- You only really need cbegin/cend if you're using auto type deduction (that's the reason they were introduced). I think it's fine to use begin/end here. --Cubbi (talk) 13:04, 15 August 2014 (PDT)
[edit] Exhaustive truth table
I keep finding myself looking at the truth table on this page when I have corner cases that don't quite fit any of the three. I sat down and made a big table of all 16 possible truth-table rows, including some that can reasonably be spelled multiple ways. It doesn't belong on the main page, but hopefully nobody minds if I leave it here. godbolt
#include <array> #include <algorithm> #include <cassert> #include <functional> // Some example arrays: static constexpr auto mixed = std::array{0, 1}; static constexpr auto allTrue = std::array{1, 1}; static constexpr auto allFalse = std::array{0, 0}; static constexpr auto none = std::array<int, 0>{}; // Shorthand: namespace r = std::ranges; static constexpr auto id = std::identity{}; // Test the truth tables from https://en.cppreference.com/w/cpp/algorithm/all_any_none_of: static_assert(false == r::all_of(mixed, id)); static_assert(true == r::all_of(allTrue, id)); static_assert(false == r::all_of(allFalse, id)); static_assert(true == r::all_of(none, id)); static_assert(true == r::any_of(mixed, id)); static_assert(true == r::any_of(allTrue, id)); static_assert(false == r::any_of(allFalse, id)); static_assert(false == r::any_of(none, id)); static_assert(false == r::none_of(mixed, id)); static_assert(false == r::none_of(allTrue, id)); static_assert(true == r::none_of(allFalse, id)); static_assert(true == r::none_of(none, id)); //! Represent a row of the truth table: enum TruthePattern : int8_t { has_true_and_false = 0b1000, has_true_not_false = 0b0100, no_trues_has_false = 0b0010, no_trues_no_falses = 0b0001, }; //! Compute the bitfield representing a row of the truth table for f(range, pred): [[nodiscard]] constexpr TruthePattern doTest(auto f, auto pred) { // Ensure that being size-one isn't special: assert(f(std::array{1}, pred) == f(allTrue, pred)); assert(f(std::array{0}, pred) == f(allFalse, pred)); return TruthePattern( (TruthePattern::has_true_and_false * f(mixed, pred)) | (TruthePattern::has_true_not_false * f(allTrue, pred)) | (TruthePattern::no_trues_has_false * f(allFalse, pred)) | (TruthePattern::no_trues_no_falses * f(none, pred))); } //! Compute the bitfield representing a row of the truth table for f(range): [[nodiscard]] constexpr TruthePattern doTest(auto f) { return doTest([&](auto&& range, std::identity) { return f(range); }, id); } // The table in the doc: static_assert(0b0101 == doTest(r::all_of, id)); static_assert(0b1100 == doTest(r::any_of, id)); static_assert(0b0011 == doTest(r::none_of, id)); // Some modifications of the three named ones: // all_of: static_assert(0b0101 == doTest(r::all_of, id)); static_assert(0b1010 == doTest(std::not_fn(r::all_of), id)); static_assert(0b0011 == doTest(r::all_of, std::not_fn(id))); static_assert(0b1100 == doTest(std::not_fn(r::all_of), std::not_fn(id))); // any_of: static_assert(0b1100 == doTest(r::any_of, id)); static_assert(0b0011 == doTest(std::not_fn(r::any_of), id)); static_assert(0b1010 == doTest(r::any_of, std::not_fn(id))); static_assert(0b0101 == doTest(std::not_fn(r::any_of), std::not_fn(id))); // none_of: static_assert(0b0011 == doTest(r::none_of, id)); static_assert(0b1100 == doTest(std::not_fn(r::none_of), id)); static_assert(0b0101 == doTest(r::none_of, std::not_fn(id))); static_assert(0b1010 == doTest(std::not_fn(r::none_of), std::not_fn(id))); //! \return true if all of them are true and it has at least one (non-empty): static constexpr auto anyAndAllOf = []<typename P = std::identity>(auto const& range, P pred = {}) { return !r::empty(range) && r::all_of(range, pred); }; //! A slower way to compute anyAndAllOf: static constexpr auto hasAndAllAre = []<typename P = std::identity>(auto const& range, P pred = {}) { return r::any_of(range, pred) && r::all_of(range, pred); }; static_assert(doTest(hasAndAllAre) == doTest(anyAndAllOf)); //! \return true iff the range is homogeneous (empty is homogeneous). static constexpr auto homogeneous = []<typename P = std::identity>(auto const& range, P pred = {}) { return r::adjacent_find(range, std::not_equal_to<>{}, pred) == std::end(range); }; //! \return true if there are mixed answers to \p pred (size zero or one returns `true`.) static constexpr auto heterogeneous = []<typename P = std::identity>(auto const& range, P pred = {}) { return !homogeneous(range, pred); }; //! \return true if the range is heterogeneous or if it's just empty. static constexpr auto heterogeneousOrEmpty = []<typename P = std::identity>(auto const& range, P pred = {}) { return r::empty(range) || heterogeneous(range, pred); }; ///////////////////////////////////////////////// // Ways to get all 16 possible truth-tables rows: static_assert(0b0000 == doTest([](auto&&) { return false; })); static_assert(0b0001 == doTest(r::empty)); static_assert(0b0010 == doTest(anyAndAllOf, std::not_fn(id))); static_assert(0b0011 == doTest(r::none_of, id)); static_assert(0b0011 == doTest(r::all_of, std::not_fn(id))); static_assert(0b0011 == doTest(std::not_fn(r::any_of), id)); static_assert(0b0100 == doTest(anyAndAllOf, id)); static_assert(0b0101 == doTest(r::all_of, id)); static_assert(0b0101 == doTest(std::not_fn(r::any_of), std::not_fn(id))); static_assert(0b0101 == doTest(r::none_of, std::not_fn(id))); static_assert(0b0110 == doTest([](auto& range) { return !r::empty(range) && homogeneous(range); })); static_assert(0b0111 == doTest(homogeneous)); static_assert(0b1000 == doTest(heterogeneous, id)); static_assert(0b1000 == doTest(std::not_fn(homogeneous))); static_assert(0b1001 == doTest(heterogeneousOrEmpty)); static_assert(0b1010 == doTest(r::any_of, std::not_fn(id))); static_assert(0b1010 == doTest(std::not_fn(r::all_of), id)); static_assert(0b1010 == doTest(std::not_fn(r::none_of), std::not_fn(id))); static_assert(0b1011 == doTest([](auto& range) { return r::empty(range) || r::any_of(range, std::not_fn(id)); })); // "any false or empty." static_assert(0b1100 == doTest(r::any_of, id)); static_assert(0b1100 == doTest(std::not_fn(r::none_of), id)); static_assert(0b1100 == doTest(std::not_fn(r::all_of), std::not_fn(id))); static_assert(0b1101 == doTest([](auto& range) { return r::empty(range) || r::any_of(range, id); })); // "any_of or empty" static_assert(0b1110 == doTest(std::not_fn(r::empty))); static_assert(0b1111 == doTest([](auto&&) { return true; }));
Where obviously if you want to get any particular row, you can always take take combinations. I also hope this is useful for reducing the expression you have in mind to a more-concise or more-readable one. BenFrantzDale (talk) 06:43, 14 March 2025 (PDT)