Document number: P?????R0
Project: Programming Language C++, Core Working Group
 
Antony Polukhin <antoshkka@gmail.com>
 
Date: 2016-01-11

A Proposal to Relax Constexpr Restrictions for some Reinterpret Casts

I. Introduction and Motivation

The Standard Library provides a great collection of containers and algorithms, many of which currently lack constexpr support. Even a simple constexpr usage requires reimplementing a big bunch of the Standard Library. Consider the simple example:

#include <array>
#include <cstring>

template <std::size_t N>
constexpr auto copy_some(const char* begin) {
    std::array<char, N> result = {};

    // ERROR: non-constexpr function 'memcpy' cannot be used in a constant expression
    std::memcpy(result.begin(), begin, N);
    return result;
}

int main () {
    constexpr char a[] = { 'H', 'e', 'l', 'l', 'o' };
    constexpr auto res = copy_some<sizeof(a)>(a);
}

This proposal concentrates on simplification of constexpr algorithms development, deferring the constexpr modifications of the standard headers to a separate proposals.

II. Impact on the Standard

This proposal is a core extension. It proposes no changes to existing headers. The changes do not break existing code and do not degrade performance.

III. Design Decisions

A. Allow conversions from void* to pointers to char, unsigned char

Existing implementations of the functions in <algorithm> header usually rely on functions from <cstring>. For example std::copy usually takes advantage of std::memmove for POD types. This makes the memory copying functions widely used all around the Standard Library.

Many of the memory copying functions accept parameters by pointers to void. This proposal relaxes only those conversions that do not affect aliasing, because some of the existing compilers rely heavily on aliasing rules.

B. Allow reinterpret_casting pointers to pointers to char, unsigned char

This is a generalization of a previous bulletin. Having the ability to cast to void pointers and from void pointers to single byte types it is possible to implement reinterpret_cast from scratch, so there's no reason for keeping the reinterpret_cast restriction any more.

C. No need to describe all the reinterpret_cast restrictions

N4567 contains restrictions on constant expressions, that make any UB code not a constant expression: [expr.const] "(2.5) — an operation that would have undefined behavior as specified in Clauses 1 through 16". So any attempt to make reinterpret_cast that results in UB will make the expression non-constant.

N4567 describes all the conversions from a function pointer to an object pointer type or vice versa as conditionally-supported, so there's no need to describe that restriction in [expr.const]: it's up to the compiler vendors to allow or disallow such conversions.

IV. Proposed modifications for N4567

All the additions to the Standard are marked with underlined green.

A. Modifications to "5.20 Constant expressions" [expr.const]

(2.11) — a conversion from type cv void * to a pointer-to-object type, other than cv char* or cv unsigned char*;
(2.12) — a dynamic cast (5.2.7);
(2.13) — a reinterpret_cast, other than a cast from cv pointer type to cv char* or cv unsigned char* (5.2.10);
		

B. Feature-testing macro

For the purposes of SG10, we recommend the feature-testing macro name __cpp_constexpr_to_char_casts.

V. Revision History

Revision 1:

VI. References

[N4567] Working Draft, Standard for Programming Language C++. Available online at www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf

[Discussion] A call to discuss asm in constexpr and constexpr <algorithm>. Available online at https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/9sTJWsOpptE

 

VII. Acknowledgements

Walter E. Brown provided numerous comments, corrections, and suggestions for this proposal.