Replace first_of_t with exactly_one_t
diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h
index 7fbdfcb..d046bdd 100644
--- a/include/pybind11/attr.h
+++ b/include/pybind11/attr.h
@@ -456,7 +456,7 @@
 
 /// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found)
 template <typename... Extra>
-using extract_guard_t = typename first_of_t<is_call_guard, call_guard<>, Extra...>::type;
+using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type;
 
 /// Check the number of named arguments at compile time
 template <typename... Extra,
diff --git a/include/pybind11/common.h b/include/pybind11/common.h
index 9e6b0e1..70743ea 100644
--- a/include/pybind11/common.h
+++ b/include/pybind11/common.h
@@ -502,20 +502,27 @@
 template <template<typename> class Predicate, typename... Ts>
 constexpr int constexpr_last() { return constexpr_impl::last(0, -1, Predicate<Ts>::value...); }
 
-// Extracts the first type from the template parameter pack matching the predicate, or Default if none match.
-template <template<class> class Predicate, class Default, class... Ts> struct first_of;
-template <template<class> class Predicate, class Default> struct first_of<Predicate, Default> {
-    using type = Default;
+/// Return the Nth element from the parameter pack
+template <size_t N, typename T, typename... Ts>
+struct pack_element { using type = typename pack_element<N - 1, Ts...>::type; };
+template <typename T, typename... Ts>
+struct pack_element<0, T, Ts...> { using type = T; };
+
+/// Return the one and only type which matches the predicate, or Default if none match.
+/// If more than one type matches the predicate, fail at compile-time.
+template <template<typename> class Predicate, typename Default, typename... Ts>
+struct exactly_one {
+    static constexpr auto found = constexpr_sum(Predicate<Ts>::value...);
+    static_assert(found <= 1, "Found more than one type matching the predicate");
+
+    static constexpr auto index = found ? constexpr_first<Predicate, Ts...>() : 0;
+    using type = conditional_t<found, typename pack_element<index, Ts...>::type, Default>;
 };
-template <template<class> class Predicate, class Default, class T, class... Ts>
-struct first_of<Predicate, Default, T, Ts...> {
-    using type = typename std::conditional<
-        Predicate<T>::value,
-        T,
-        typename first_of<Predicate, Default, Ts...>::type
-    >::type;
-};
-template <template<class> class Predicate, class Default, class... T> using first_of_t = typename first_of<Predicate, Default, T...>::type;
+template <template<typename> class P, typename Default>
+struct exactly_one<P, Default> { using type = Default; };
+
+template <template<typename> class Predicate, typename Default, typename... Ts>
+using exactly_one_t = typename exactly_one<Predicate, Default, Ts...>::type;
 
 /// Defer the evaluation of type T until types Us are instantiated
 template <typename T, typename... /*Us*/> struct deferred_type { using type = T; };
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index 9a3af8e..cdf5f1a 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -888,9 +888,9 @@
 
 public:
     using type = type_;
-    using type_alias = detail::first_of_t<is_subtype, void, options...>;
+    using type_alias = detail::exactly_one_t<is_subtype, void, options...>;
     constexpr static bool has_alias = !std::is_void<type_alias>::value;
-    using holder_type = detail::first_of_t<is_holder, std::unique_ptr<type>, options...>;
+    using holder_type = detail::exactly_one_t<is_holder, std::unique_ptr<type>, options...>;
     using instance_type = detail::instance<type, holder_type>;
 
     static_assert(detail::all_of<is_valid_class_option<options>...>::value,
@@ -1158,15 +1158,12 @@
     using class_<Type>::def;
     using class_<Type>::def_property_readonly_static;
     using Scalar = typename std::underlying_type<Type>::type;
-    template <typename T> using arithmetic_tag = std::is_same<T, arithmetic>;
 
     template <typename... Extra>
     enum_(const handle &scope, const char *name, const Extra&... extra)
       : class_<Type>(scope, name, extra...), m_entries(), m_parent(scope) {
 
-        constexpr bool is_arithmetic =
-            !std::is_same<detail::first_of_t<arithmetic_tag, void, Extra...>,
-                          void>::value;
+        constexpr bool is_arithmetic = detail::any_of<std::is_same<arithmetic, Extra>...>::value;
 
         auto m_entries_ptr = m_entries.inc_ref().ptr();
         def("__repr__", [name, m_entries_ptr](Type value) -> pybind11::str {