Constexpr Library Additions: functional N3789 2013-09-27 Marshall Clow, mclow.lists@gmail.com Modification History: * This is a revision of N3749. Added changes to the synopsis. Rationale: The named C++ function objects (less, equals, greater_equal, etc) are used throughout the standard library as an intermediate between code that needs to manipulate objects and the fundamental operators (operator <, ==, >= respectively). In C++14, many of these fundamental operators have been marked as constexpr (for some types; chrono, complex, optional, etc). But you if you use the named operators, then you lose the ability to work at compile time. For example: template struct less { typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; bool operator()(const T& x, const T& y) const { return x < y; } }; less{}(x,y) can never be evaluated at compile time. This is especially a problem for the proposed std::optional, which defines its' operator < as being constexpr, and yet requires it to use std::less to do the comparisons [ 20.6.8, p 4,5,6 ]. optional's operators cannot be executed at compile time except for the simple case where the optional is disengaged. I propose that we make the following change: template struct less { typedef T first_argument_type; typedef T second_argument_type; typedef bool result_type; constexpr bool operator()(const T& x, const T& y) const { return x < y; } }; This will allow people to use less{}(x,y) at compile time. This should also apply to all the relational operators (less, greater, less_equal, greater_equal, not_equal_to, equal_to), the arithmetic operators (plus, minus, multiplies, divides, modulus, negates), the bit manipulations (bit_and, bit_or, bit_xor, bit_not) and the negators (unary_negate, binary_negate, no1, not2). Proposed Wording All changes are relative to N3691): === Amend header synopsis section 20.10 p2 as follows: // 20.10.8, negators: template class unary_negate; template constexpr unary_negate not1(const Predicate&); template class binary_negate; template constexprbinary_negate not2(const Predicate&); === Amend section 20.10.4 as follows: template struct plus { constexpr T operator()(const T& x, const T& y) const; template struct minus { constexpr T operator()(const T& x, const T& y) const; template struct multiplies { constexpr T operator()(const T& x, const T& y) const; template struct divides { constexpr T operator()(const T& x, const T& y) const; template struct modulus { constexpr T operator()(const T& x, const T& y) const; template struct negate { constexpr T operator()(const T& x) const; template <> struct plus { template constexpr auto operator()(T&& t, U&& u) const template <> struct minus { template constexpr auto operator()(T&& t, U&& u) const template <> struct multiplies { template constexpr auto operator()(T&& t, U&& u) const template <> struct divides { template constexpr auto operator()(T&& t, U&& u) const template <> struct modulus { template constexpr auto operator()(T&& t, U&& u) const template <> struct negate { template constexpr auto operator()(T&& t) const === Amend section 20.10.5 as follows: template struct equal_to { constexpr bool operator()(const T& x, const T& y) const; template struct not_equal_to { constexpr bool operator()(const T& x, const T& y) const; template struct greater { constexpr bool operator()(const T& x, const T& y) const; template struct less { constexpr bool operator()(const T& x, const T& y) const; template struct greater_equal { constexpr bool operator()(const T& x, const T& y) const; template struct less_equal { constexpr bool operator()(const T& x, const T& y) const; template <> struct equal_to { template constexpr auto operator()(T&& t, U&& u) const template <> struct not_equal_to { template constexpr auto operator()(T&& t, U&& u) const template <> struct greater { template constexpr auto operator()(T&& t, U&& u) const template <> struct less { template constexpr auto operator()(T&& t, U&& u) const template <> struct greater_equal { template constexpr auto operator()(T&& t, U&& u) const template <> struct less_equal { template constexpr auto operator()(T&& t, U&& u) const === Amend section 20.10.6 as follows: template struct logical_and { constexpr bool operator()(const T& x, const T& y) const; template struct logical_or { constexpr bool operator()(const T& x, const T& y) const; template struct logical_not { constexpr bool operator()(const T& x) const; template <> struct logical_and { template constexpr auto operator()(T&& t, U&& u) const template <> struct logical_or { template constexpr auto operator()(T&& t, U&& u) const template <> struct logical_not { template constexpr auto operator()(T&& t) const === Amend section 20.10.7 as follows: template struct bit_and { constexpr T operator()(const T& x, const T& y) const; template struct bit_or { constexpr T operator()(const T& x, const T& y) const; template struct bit_xor { constexpr T operator()(const T& x, const T& y) const; template struct bit_not { constexpr T operator()(const T& x) const; template <> struct bit_and { template constexpr auto operator()(T&& t, U&& u) const template <> struct bit_or { template constexpr auto operator()(T&& t, U&& u) const template <> struct bit_xor { template constexpr auto operator()(T&& t, U&& u) const template <> struct bit_not { template constexpr auto operator()(T&& t) const === Amend section 20.10.8 as follows: template class unary_negate { public: explicit constexpr unary_negate(const Predicate& pred); constexpr bool operator()(const typename Predicate::argument_type& x) const; template constexpr unary_negate not1(const Predicate& pred); template class binary_negate { public: explicit constexpr binary_negate(const Predicate& pred); constexpr bool operator()(const typename Predicate::first_argument_type& x, const typename Predicate::second_argument_type& y) const; template constexpr binary_negate not2(const Predicate& pred);