@@ -100,6 +100,18 @@ I Reduce(std::function<I(I&&, I&&)> red, std::vector<I>&& vec) {
100100 return res;
101101}
102102
103+ namespace {
104+ // Allow combinations:
105+ // LHS RHS
106+ // const T and T
107+ // const T and const T
108+ template <typename LHS, typename RHS>
109+ struct is_same_allow_rhs_non_const {
110+ const static bool value =
111+ std::is_same<LHS, typename std::add_const<RHS>::type>::value;
112+ };
113+ } // namespace
114+
103115/*
104116 * Return a copy of the vector that contains only those elements for which
105117 * function "f" returns true.
@@ -108,8 +120,12 @@ I Reduce(std::function<I(I&&, I&&)> red, std::vector<I>&& vec) {
108120 * functor) with signature <bool(T)>.
109121 *
110122 * Template argument deduction takes care of vector<const T> cases
111- * automatically. Note that the signature of "f" must use the same type, that
112- * is "const T".
123+ * automatically. Additionally, accept vectors of (pointers to) non-const
124+ * elements and a function with (a pointer to) a const argument.
125+ * Note that the function type is a template argument guarded by static asserts
126+ * rather than an std::function because template argument deduction fails on
127+ * lambdas in the latter case; lambdas are convertible to std::function but are
128+ * not an instance of std::function.
113129 */
114130template <typename Func, typename T>
115131std::vector<T> Filter (Func f, const std::vector<T>& input) {
@@ -119,9 +135,25 @@ std::vector<T> Filter(Func f, const std::vector<T>& input) {
119135 static_assert (
120136 function_traits<Func>::n_args == 1 ,
121137 " Filtering function must take one argument" );
138+
139+ // Allow combinations:
140+ // Function arg Vector element
141+ // T and T
142+ // const T and T
143+ // const T and const T
144+ // T* and T*
145+ // const T* and T*
146+ // const T* and const T*
147+ using arg0 = typename function_traits<Func>::template arg<0 >::type;
148+ constexpr bool sameType = std::is_same<arg0, T>::value;
149+ constexpr bool sameTypeRightMbConst =
150+ is_same_allow_rhs_non_const<arg0, T>::value;
151+ constexpr bool ptrToSameTypeRightMbConst = std::is_pointer<arg0>::value &&
152+ std::is_pointer<T>::value &&
153+ is_same_allow_rhs_non_const<typename std::remove_pointer<arg0>::type,
154+ typename std::remove_pointer<T>::type>::value;
122155 static_assert (
123- std::is_same<typename function_traits<Func>::template arg<0 >::type, T>::
124- value,
156+ sameType || sameTypeRightMbConst || ptrToSameTypeRightMbConst,
125157 " The argument of the filtering function must have the same type "
126158 " as the element type of the collection being filtered" );
127159
0 commit comments