Hi,
Suppose I want to write this function...
template < typename I, typename P >
// requires I is a InputIterator
// P is a Predicate(ValueType(I))
bool all_of_negated( I f, I l, P p )
{
return std::all_of( f, l, std::not1(p) );
}
... and I want to use it in this way...
void foo()
{
vector<int> vi { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
bool aon = all_of_negated( begin(vi), end(vi), []( int x ) { return true; } );
}
The function all_of_negated is incorrect acording to the Standard (n3691) because std::unary_negate requires that its template parameter has a typedef named argument_type.
See...
20.10.8 Negators [negators]
1 Negators not1 and not2 take a unary and a binary predicate, respectively, and return their complements
(5.3.1).
template <class Predicate>
class unary_negate {
public:
explicit unary_negate(const Predicate& pred);
bool operator()(const typename Predicate::argument_type& x) const;
typedef typename Predicate::argument_type argument_type;
typedef bool result_type;
};
I believe that the standard does not define the requirements for Predicate
I have checked the "Elements of Programming" and "N3351 - A Concept Design for the STL".
None of them require that Predicate contains argument_type.
Posible Solutions:
A. Not use not1
template < typename I, typename P >
// requires I is a InputIterator
// P is a Predicate(ValueType(I))
bool all_of_negated( I f, I l, P p )
{
return std::all_of( f, l, [p]( typename I::value_type const& x ) { return !p(x); } );
}
I don't like it. I want to use not1.
B. Redefine unary_negate
template <class Predicate>
class unary_negate {
public:
explicit unary_negate(const Predicate& pred);
template <typename T>
// requires P is a Predicate(T)
bool operator()(const T& x) const;
typedef bool result_type;
};
backward compatibility break?
C. Redefine unary_negate and use TypeTraits (or Concept) for Function Arguments?
template <class Predicate>
class unary_negate {
public:
explicit unary_negate(const Predicate& pred);
bool operator()(const typename argument<Predicate, 0>::type& x) const;
typedef typename argument<Predicate, 0>::type argument_type;
typedef bool result_type;
};
We have to create this kind of TypeTraits.
Is it possible?
I'll stick with option B, and I think that all the requirements for argument_type, first_argument_type and second_argument_type should be removed from the Standard.
What do you think?
Kind regards,
Fernando Pelliccioni.