<html>
<head>
<TITLE>
ISO/IEC JTC1/SC22/WG21
N3749
</TITLE>
</head>
<body>
<h1>
<img align=top src="/pics/iso44.gif" alt="ISO/">
<img align=top src="/pics/iec44.gif" alt="IEC">
JTC1/SC22/WG21
N3749
</h1>
<pre>
Constexpr Library Additions: functional 
N3749 
2013-08-31
Marshall Clow, mclow.lists@gmail.com


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 &lt;, ==, >=
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 &lt;class T = void> 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 &lt; y; }
		};

less&lt;T>{}(x,y) can never be evaluated at compile time.

This is especially a problem for the proposed std::optional&lt;T>, which defines
its' operator &lt; 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 &lt;class T = void> 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 &lt; y; }
		};

This will allow people to use less&lt;T>{}(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 <a hRef="../2013/n3691.pdf">N3691</a>):

=== Amend section 20.10.4 as follows:

template &lt;class T = void> struct plus {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;
     
template &lt;class T = void> struct minus {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;
  
template &lt;class T = void> struct multiplies {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;
  
template &lt;class T = void> struct divides {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;
  
template &lt;class T = void> struct modulus {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;
  
template &lt;class T = void> struct negate {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x) const;

template &lt;> struct plus&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct minus&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const
  
template &lt;> struct multiplies&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct divides&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct modulus&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const
  
template &lt;> struct negate&lt;void> {
  template &lt;class T> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t) const
  
=== Amend section 20.10.5 as follows:

template &lt;class T = void> struct equal_to {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;
 
template &lt;class T = void> struct not_equal_to {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;class T = void> struct greater {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;class T = void> struct less {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;class T = void> struct greater_equal {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;class T = void> struct less_equal {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;> struct equal_to&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct not_equal_to&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct greater&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct less&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct greater_equal&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct less_equal&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

=== Amend section 20.10.6 as follows:

template &lt;class T = void> struct logical_and {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;class T = void> struct logical_or {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x, const T& y) const;

template &lt;class T = void> struct logical_not {
  &lt;INS>constexpr&lt;/INS> bool operator()(const T& x) const;

template &lt;> struct logical_and&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct logical_or&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct logical_not&lt;void> {
  template &lt;class T> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t) const
  
=== Amend section 20.10.7 as follows:

template &lt;class T = void> struct bit_and {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;

template &lt;class T = void> struct bit_or {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;

template &lt;class T = void> struct bit_xor {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x, const T& y) const;

template &lt;class T = void> struct bit_not {
  &lt;INS>constexpr&lt;/INS> T operator()(const T& x) const;

template &lt;> struct bit_and&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct bit_or&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct bit_xor&lt;void> {
  template &lt;class T, class U> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t, U&& u) const

template &lt;> struct bit_not&lt;void> {
  template &lt;class T> &lt;INS>constexpr&lt;/INS> auto operator()(T&& t) const

=== Amend section 20.10.8 as follows:

template &lt;class Predicate>
  class unary_negate {
  public:
     explicit &lt;INS>constexpr&lt;/INS> unary_negate(const Predicate& pred);
     &lt;INS>constexpr&lt;/INS> bool operator()(const typename Predicate::argument_type& x) const;

template &lt;class Predicate>
   &lt;INS>constexpr&lt;/INS> unary_negate&lt;Predicate> not1(const Predicate& pred);

template &lt;class Predicate>
  class binary_negate {
  public:
  explicit &lt;INS>constexpr&lt;/INS> binary_negate(const Predicate& pred);
  &lt;INS>constexpr&lt;/INS> bool operator()(const typename Predicate::first_argument_type& x,
      const typename Predicate::second_argument_type& y) const;

template &lt;class Predicate>
   &lt;INS>constexpr&lt;/INS> binary_negate&lt;Predicate> not2(const Predicate& pred);
</pre>
</body>
</html>
