**Document number**: P0827R0  
**Date**: 2017-10-16  
**Reply-to**: John McFarlane, [cnl@john.mcfarlane.name](mailto:cnl@john.mcfarlane.name)  
**Reply-to**: Louis Dionne, [ldionne.2@gmail.com](mailto:ldionne.2@gmail.com)  
**Audience**: SG6, SG14, LEWG  

# General-Purpose Constant Value Type

## Introduction

A constant value type can make some arithmetic operations more efficient.
For example, some low-level operations using the fixed-point type in [[P0037](http://wg21.link/p0037)] effectively become no-ops:

```c++
auto a = fixed_point<int, -10>{1};  // fixed-point wrapper around an int with resolution 2^-10
auto b = a << 1;  // fixed_point<int, -10>{2}, requires a run-time shift operation
auto c = a << integral_constant<int, 1>{};  // fixed_point<int, -9>{2}, bitwise equal to a; only the type has changed
```

Combined with a user-defined literal, this code can be made almost as terse and readable as the run-time code:

```c++
auto d = a << 1static;
```

Many other examples exists of situations where the value of an argument might affect the type of a result:

```c++
// snug returns the narrowest type that can hold the given value
auto e = snug(100);     // sizeof(e) == sizeof(int), snug cannot determine type from value
auto f = snug(100static);    // sizeof(f) == sizeof(int8_t), but it can determine type from type
```

This feature would also interact well with class template argument deduction:

```c++
auto g = fixed_point(0x100);    // fixed_point<int, 0>{256}, type cannot be determined based on initial value
auto h = fixed_point(0x100static); // fixed_point<int, 8>{256}, 8 fewer bits are devoted to low-order bits
```

Currently, the only standard type for expressing a constant value types is `integral_constant` which has drawbacks:

1. It requires that two template parameters be specified where `template<auto>` would mean only one was necessary.
2. If future revisions to the standard relax restrictions on non-type template parameters, 
   it will be ill-named and ill-prepared.
3. A lack of operator overloads means that results of many operations are values, e.g.:

   ```c++
   auto g = integral_constant<int, 2>{} + integral_constant<int, 2>{};
   // result is 4, not integral_constant<int, 4>{}
   ```

We propose a replacement for `integral_constant` called `constant` and an accompanying user-defined literal 
which address the above issues.

## Prior Art

A similar proposal to improve on `integral_constant` was made 
in [P0377](http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0377r0.html).
It addresses the first of the three drawbacks listed above: 
namely eliminating `integral_constant`'s type template parameter.
But it does not address the other two.

User-defined literals returning an constant value type can be found in multiple libraries and on forums including in
[[Boost.Hana](http://www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/structboost_1_1hana_1_1integral__constant.html#a1c078fd00db48686ca9e0aa17f47344e)] 
and [[CNL](https://github.com/johnmcfarlane/cnl/blob/develop/include/cnl/integral_constant.h#L100)].

## Details

### Definition of `constant`

```c++
template<auto Value>
struct constant {
    using value_type = decltype(Value);
    static constexpr value_type value = Value;

    constexpr operator value_type() const {
        return value;
    }
};
```

The implicit conversion operator ensures that `constant` objects are as easy to use as the variable they mimic.
In the following example, the result of `!=` is `constant<false>` which is then implicitly converted to `bool`:

```c++
static_assert(constant<1>{} != constant<2>{});
```

### Operator Overloads

A complete set of unary and binary operators ensure 
that operations taking only `constant` operands do not return non-`constant` results:

```c++
// unary operator @
template<auto Value1>
constexpr auto operator@(constant<Value1> rhs) noexcept {
    return constant<@ Value1>{};
}

// binary operator @
template<auto Value1, auto Value2>
constexpr auto operator@(constant<Value1> lhs, constant<Value2> rhs) noexcept {
    return constant<Value1 @ Value2>{};
}
```

### User-Defined Literals

A user-defined literal returns `constant` objects of values of type, `maxint_t`.

```c++
namespace literals {
    template<char ... Chars>
    constexpr auto operator ""static() noexcept;
}
```

(Suffix, `static`, is by no means final.
Unfortunately, preferred suffix, `c`, is not suitable for combination with hexadecimal literals.)

The input string could contain whole numbers in a variety of bases:

```c++
using namespace literals;
auto i = 1000000000000static;  // constant<1000000000000LL>
auto j = 0x401static;    // constant<1025LL>
auto k = 0b10000static;  // constant<16LL>
auto l = 077static;  // constant<63LL>
```

## Discussion

The use of a pack of `char` as input to `operator ""static` is limiting.
However, there is currently no better alternative.
Future language revisions may allow some improvements:

* fractional values, e.g. with a decimal place;
* non-string input and
* greater range than `intmax_t`.

Care should be taken to ensure the current design does not preclude these possibilities. 

## Reference Implementation

A simple proof of concept is available on 
[[CompilerExplorer](https://godbolt.org/g/vXpEmX)].
