<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
		<title>Constexpr for std::char_traits</title>
		<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
		<meta http-equiv="Content-Language" content="en-us">
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

		<style type="text/css">
			.addition { color: green; text-decoration: underline; }
			.right { float:right; }
			.desc { margin-left: 35px; margin-top: 10px; padding:0; white-space: normal; }
			.changed-deleted { background-color: #CFF0FC ; text-decoration: line-through; display: none; }
			.addition.changed-deleted { color: green; background-color: #CFF0FC ; text-decoration: line-through; text-decoration: black double line-through; display: none; }
			.changed-added { background-color: #CFF0FC ;}
			body {max-width: 1024px; margin-left: 25px;}
			.cppkeyword { color: blue; }
			.cppcomment { color: green; }
			.cppcomment > .cppkeyword{ color: green; }
			.cpptext { color: #2E8B57; }
		</style>
	</head>
	<body bgcolor="#ffffff">
		<address>Document number: P0426R1</address>
		<address>Project: Programming Language C++</address>
		<address>Audience: Library Evolution Working Group</address>
		<address>&nbsp;</address>
		<address>Antony Polukhin &lt;<a href="mailto:antoshkka@gmail.com">antoshkka@gmail.com</a>&gt;, &lt;<a href="mailto:antoshkka@yandex-team.ru">antoshkka@yandex-team.ru</a>&gt;</address>
		<address>&nbsp;</address>
		<address>Date: 2016-11-08</address>
		<h1>Constexpr for std::char_traits</h1>

		<h2>I. Introduction and Motivation</h2>
		<p>There is a request in the "C++ Standard Library Active Issues List" for <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2232">The char_traits specializations should declare their length(), compare(), and find() members constexpr</a>. Currently the following code fails to compile:</p>

		<p></p><blockquote><pre>#include &lt;string_view&gt;
//  Compile time error:
//  &gt; error: constexpr variable 'service' must be initialized by a constant expression
//  &gt; constexpr string_view service = "HELLO WORD SERVICE";
//  &gt;                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  &gt; string_view:110:39: note: non-constexpr function 'length' cannot be used in a constant expression
//
constexpr string_view service = "HELLO WORD SERVICE";
</pre></blockquote><p></p>

		<p>This proposal attempts to solve the issue 2232 and make <code>std::string_view</code> usable in constant expressions.</p>
		<p><code>std::basic_string_view</code> uses from <code>traits_type</code> only the static member functions <code>length</code>, <code>compare</code> and <code>find</code>. Only those functions are affected by this proposal.</p>

		<p>A proof of concept implementation with benchmark is available at: <a href="https://github.com/apolukhin/apolukhin.github.io/tree/master/papers/constexpr_char_traits/">constexpr char_traits</a>.
		</p>


		<h2>II. Impact on the Standard</h2>
		<p>This proposal is a pure library extension. It proposes changes to the
			existing header <code>&lt;string&gt;</code> such that the changes do not break existing code
			and do not degrade performance. It does not require any changes in the core 
			language and it can be (and has been) implemented in standard C++.
		</p>

		<h2>III. Analysis of existing <code>std::char_traits</code> implementations.</h2>
		<p>libstdc++ and libc++ have implementations of <code>std::char_traits&lt;char16_t&gt;</code> and <code>std::char_traits&lt;char32_t&gt;</code> that do not use C functions or intrinsics. Those two <code>std::char_traits</code> could be made constexpr without any impact on performance.</p>

		<p>libstdc++ uses <code>__builtin_strlen</code>, <code>__builtin_memcmp</code> and <code>__builtin_memchr</code> intrinsics for <code>std::char_traits&lt;char&gt;</code>. Those extensions are already usable in constant expressions.</p>

		<p>libstdc++ uses C functions for <code>std::char_traits&lt;wchar_t&gt;</code>; libc++ uses C functions for <code>std::char_traits&lt;char&gt;</code> and <code>std::char_traits&lt;wchar_t&gt;</code>.</p>
		<p>Implementations of standard library, C library and compilers may differ a lot, but according to the performance measures from <a href="#appendix">"Appendix"</a> following conclusions could be made for eglibc-2.19:</p>
		<ul>
			<li><code>char</code> related intrinsics outperform C calls</li>
			<li><code>char</code> related intrinsics significantly outperform hand-made naïve implementation</li>
			<li>hand-made naïve implementations may outperform C functions on short <code>wchar_t</code> strings</li>
		</ul>
		<p>Assuming that the situation in mostly the same on different platforms, it seems reasonable to:</p>
		<ul>
			<li>use intrinsics to make <code>std::char_traits&lt;char&gt;</code> constexpr. Typically this brings performance improvement.</li>
			<li>create constexpr-usable intrinsics for <code>std::char_traits&lt;wchar_t&gt;</code> or leave it non-constexpr. Two wordings are provided in this paper: one that does not mark <code>std::char_traits&lt;wchar_t&gt;</code> functions with <code>constexpr</code> and another one that does.</li>
		</ul>

		<h2>IV. Proposed wording relative to the Working Draft N4604.</h2>
		<h3>A. Wording that affects all the <code>std::char_traits</code></h3>
		<p><b>Note for editor:</b> Add constexpr in all the 21.2.3.* [char.traits.specializations.*]:</p>
		<pre>        static <span class="addition">constexpr</span> void assign(char_type& c1, const char_type& c2) noexcept;
        static <span class="addition">constexpr</span> int compare(const char_type* s1, const char_type* s2, size_t n);
        static <span class="addition">constexpr</span> size_t length(const char_type* s);
        static <span class="addition">constexpr</span> const char_type* find(const char_type* s, size_t n, const char_type&amp; a);
		</pre>

		<h3>B. Feature-testing macro</h3>
		<p>For the purposes of SG10, we recommend the feature-testing macro name <code>__cpp_lib_constexpr_char_traits</code>.</p>


		<h2>V. Revision History</h2>
		<p>Revision 1:</p>
		<ul>
			<li>
				Left the first wording only.
			</li>
			<li>
				Added constexpr to assign(char_type& c1, const char_type& c2) as LWG and LEWG wanted.
			</li>
		</ul>
		<p>Revision 0:</p>
		<ul>
			<li>
				Initial proposal.
			</li>
		</ul>


		<h2>VI. References</h2>
		<p>[<a name="N4604">N4604</a>] C++17 CD Ballot Document. Available online at
					<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4604.pdf">www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4604.pdf</a>.</p>
		<p>[<a name="Antony Polukhin">Antony Polukhin</a>] Proof of concept implementation.
			Available online at <a href="https://github.com/apolukhin/apolukhin.github.io/tree/master/papers/constexpr_char_traits/">
				https://github.com/apolukhin/apolukhin.github.io/tree/master/papers/constexpr_char_traits/</a>.
			</p>
		<p>[<a name="LWG2232">LWG2232</a>] The char_traits specializations should declare their length(), compare(), and find() members constexpr. Available online at
					<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2232">
				http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2232</a>.
			</p>
		<p>&nbsp;</p>


		<h2>VII. Acknowledgements</h2>
		<p>Walter E. Brown provided corrections and suggestions for this proposal.</p>


		<h2 id="appendix">VIII. Appendix.</h2>
		<p>Below are results of performance measures for different 
implementations of char_traits. Full output of benchmark and source 
codes are available online at <a href="https://github.com/apolukhin/apolukhin.github.io/tree/master/papers/constexpr_char_traits/">https://github.com/apolukhin/apolukhin.github.io/tree/master/papers/constexpr_char_traits/</a>.</p>
		<p>First column in output describes the length of each char array that
 was given to the trait's function. Second and third columns show the 
median value of 500 runs of trait's function on 10000 char arrays in 
microseconds.
		Column "Relation" is equal to the second column divided on the third 
column. Last column is equal to <i>max(mean absolute diviation of first trait's function runs, mean absolute diviation of second trait's function runs)</i>.</p>

		<p>Clang results:</p>
		<pre>TypeTrait::length
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             40                                 48                                 1.20       +/-0.00
20             64                                 67                                 1.05       +/-0.00
30             64                                 66                                 1.03       +/-0.00
40             64                                 66                                 1.03       +/-0.00
50             65                                 69                                 1.06       +/-0.00
500            234                                233                                1.00       +/-0.01
5000           285                                285                                1.00       +/-0.01
50000          335                                333                                0.99       +/-0.02

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             40                                 68                                 1.70       +/-0.00
20             63                                 131                                2.08       +/-0.00
30             64                                 199                                3.11       +/-0.00
40             64                                 274                                4.28       +/-0.00
50             65                                 309                                4.75       +/-0.00
500            226                                651                                2.88       +/-0.01
5000           287                                713                                2.48       +/-0.02
50000          342                                781                                2.28       +/-0.02

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             67                                 68                                 1.01       +/-0.00
20             129                                92                                 0.71       +/-0.00
30             200                                118                                0.59       +/-0.00
40             272                                147                                0.54       +/-0.00
50             307                                177                                0.58       +/-0.01
500            911                                796                                0.87       +/-0.03
5000           1108                               1000                               0.90       +/-0.02
50000          1742                               1526                               0.88       +/-0.01


TypeTrait::find
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             32                                 49                                 1.53       +/-0.00
20             94                                 86                                 0.91       +/-0.00
30             94                                 87                                 0.93       +/-0.00
40             98                                 92                                 0.94       +/-0.00
50             103                                100                                0.97       +/-0.00
500            278                                278                                1.00       +/-0.00
5000           308                                307                                1.00       +/-0.02
50000          355                                356                                1.00       +/-0.03

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             32                                 85                                 2.66       +/-0.00
20             94                                 161                                1.71       +/-0.00
30             94                                 236                                2.51       +/-0.00
40             98                                 321                                3.28       +/-0.00
50             103                                363                                3.52       +/-0.00
500            272                                784                                2.88       +/-0.01
5000           296                                781                                2.64       +/-0.03
50000          356                                872                                2.45       +/-0.04

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             86                                 120                                1.40       +/-0.00
20             164                                154                                0.94       +/-0.00
30             241                                198                                0.82       +/-0.00
40             334                                230                                0.69       +/-0.00
50             377                                277                                0.73       +/-0.00
500            1126                               937                                0.83       +/-0.01
5000           1305                               1102                               0.84       +/-0.02
50000          1488                               1305                               0.88       +/-0.00


TypeTrait::find2
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             46                                 43                                 0.93       +/-0.00
20             79                                 82                                 1.04       +/-0.00
30             79                                 82                                 1.04       +/-0.00
40             84                                 88                                 1.05       +/-0.00
50             94                                 93                                 0.99       +/-0.00
500            251                                252                                1.00       +/-0.00
5000           331                                331                                1.00       +/-0.02
50000          379                                378                                1.00       +/-0.02

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             46                                 87                                 1.89       +/-0.00
20             79                                 161                                2.04       +/-0.00
30             79                                 237                                3.00       +/-0.00
40             84                                 343                                4.08       +/-0.00
50             94                                 386                                4.11       +/-0.00
500            250                                784                                3.14       +/-0.00
5000           323                                793                                2.46       +/-0.02
50000          388                                886                                2.28       +/-0.02

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             86                                 123                                1.43       +/-0.00
20             163                                160                                0.98       +/-0.00
30             240                                203                                0.85       +/-0.00
40             350                                234                                0.67       +/-0.00
50             393                                282                                0.72       +/-0.00
500            1095                               908                                0.83       +/-0.01
5000           1248                               1092                               0.88       +/-0.03
50000          1476                               1326                               0.90       +/-0.01


TypeTrait::compare
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             59                                 40                                 0.68       +/-0.00
20             48                                 42                                 0.88       +/-0.00
30             51                                 45                                 0.88       +/-0.00
40             62                                 55                                 0.89       +/-0.00
50             72                                 61                                 0.85       +/-0.00
500            317                                317                                1.00       +/-0.00
5000           3569                               3570                               1.00       +/-0.00
50000          28745                              28679                              1.00       +/-0.00

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             59                                 95                                 1.61       +/-0.00
20             48                                 181                                3.77       +/-0.00
30             51                                 267                                5.24       +/-0.00
40             62                                 355                                5.73       +/-0.00
50             72                                 441                                6.12       +/-0.00
500            317                                4487                               14.15      +/-0.01
5000           3572                               44655                              12.50      +/-0.00
50000          28724                              461979                             16.08      +/-0.00

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             92                                 64                                 0.70       +/-0.00
20             168                                122                                0.73       +/-0.00
30             248                                125                                0.50       +/-0.00
40             332                                154                                0.46       +/-0.00
50             418                                172                                0.41       +/-0.00
500            4407                               1572                               0.36       +/-0.01
5000           43248                              14056                              0.33       +/-0.00
50000          431685                             112438                             0.26       +/-0.00

		</pre>

		<p>GCC results:</p>
		<pre>TypeTrait::length
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             34                                 40                                 1.18       +/-0.00
20             56                                 56                                 1.00       +/-0.00
30             56                                 56                                 1.00       +/-0.00
40             56                                 56                                 1.00       +/-0.00
50             60                                 60                                 1.00       +/-0.00
500            238                                241                                1.01       +/-0.00
5000           303                                304                                1.00       +/-0.01
50000          348                                351                                1.01       +/-0.03

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             34                                 60                                 1.76       +/-0.00
20             57                                 126                                2.21       +/-0.00
30             56                                 194                                3.46       +/-0.00
40             56                                 272                                4.86       +/-0.00
50             60                                 299                                4.98       +/-0.00
500            238                                596                                2.50       +/-0.00
5000           304                                632                                2.08       +/-0.01
50000          380                                708                                1.86       +/-0.04

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             62                                 79                                 1.27       +/-0.00
20             128                                103                                0.80       +/-0.00
30             190                                124                                0.65       +/-0.01
40             273                                152                                0.56       +/-0.00
50             294                                180                                0.61       +/-0.01
500            822                                839                                1.02       +/-0.00
5000           1004                               1000                               1.00       +/-0.02
50000          1643                               1538                               0.94       +/-0.01


TypeTrait::find
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             49                                 42                                 0.86       +/-0.00
20             70                                 70                                 1.00       +/-0.00
30             70                                 70                                 1.00       +/-0.00
40             82                                 77                                 0.94       +/-0.00
50             94                                 96                                 1.02       +/-0.00
500            284                                285                                1.00       +/-0.00
5000           313                                311                                0.99       +/-0.03
50000          362                                360                                0.99       +/-0.04

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             49                                 83                                 1.69       +/-0.00
20             70                                 145                                2.07       +/-0.00
30             70                                 212                                3.03       +/-0.00
40             82                                 267                                3.26       +/-0.00
50             94                                 330                                3.51       +/-0.00
500            281                                772                                2.75       +/-0.00
5000           307                                777                                2.53       +/-0.04
50000          369                                893                                2.42       +/-0.05

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             100                                174                                1.74       +/-0.00
20             180                                208                                1.16       +/-0.00
30             262                                255                                0.97       +/-0.00
40             342                                295                                0.86       +/-0.00
50             391                                347                                0.89       +/-0.00
500            1119                               1103                               0.99       +/-0.01
5000           1300                               1335                               1.03       +/-0.01
50000          1542                               1582                               1.03       +/-0.01


TypeTrait::find2
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             33                                 39                                 1.18       +/-0.00
20             77                                 86                                 1.12       +/-0.00
30             77                                 86                                 1.12       +/-0.00
40             88                                 91                                 1.03       +/-0.00
50             92                                 97                                 1.05       +/-0.00
500            272                                274                                1.01       +/-0.00
5000           339                                337                                0.99       +/-0.02
50000          389                                386                                0.99       +/-0.02

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             33                                 85                                 2.58       +/-0.00
20             77                                 161                                2.09       +/-0.00
30             77                                 242                                3.14       +/-0.00
40             88                                 321                                3.65       +/-0.00
50             92                                 371                                4.03       +/-0.00
500            264                                801                                3.03       +/-0.00
5000           340                                811                                2.39       +/-0.02
50000          384                                869                                2.26       +/-0.03

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             84                                 116                                1.38       +/-0.00
20             162                                150                                0.93       +/-0.00
30             240                                194                                0.81       +/-0.00
40             322                                225                                0.70       +/-0.00
50             373                                274                                0.73       +/-0.00
500            1073                               901                                0.84       +/-0.01
5000           1233                               1102                               0.89       +/-0.01
50000          1481                               1356                               0.92       +/-0.02


TypeTrait::compare
String length  intrinsics&lt;char&gt;                   c_calls&lt;char&gt;                      Relation   +/-deviation
10             54                                 40                                 0.74       +/-0.00
20             47                                 47                                 1.00       +/-0.00
30             50                                 43                                 0.86       +/-0.00
40             54                                 54                                 1.00       +/-0.00
50             70                                 56                                 0.80       +/-0.00
500            316                                318                                1.01       +/-0.00
5000           3589                               3503                               0.98       +/-0.01
50000          28598                              28577                              1.00       +/-0.00

String length  intrinsics&lt;char&gt;                   hand-made&lt;char&gt;                    Relation   +/-deviation
10             54                                 95                                 1.76       +/-0.00
20             47                                 184                                3.91       +/-0.00
30             50                                 273                                5.46       +/-0.00
40             54                                 399                                7.39       +/-0.00
50             70                                 476                                6.80       +/-0.00
500            314                                3431                               10.93      +/-0.00
5000           3590                               33538                              9.34       +/-0.00
50000          28582                              333971                             11.68      +/-0.00

String length  hand-made&lt;wchar_t&gt;                 std::char_traits&lt;wchar_t&gt;          Relation   +/-deviation
10             113                                57                                 0.50       +/-0.00
20             210                                121                                0.58       +/-0.00
30             307                                119                                0.39       +/-0.00
40             444                                158                                0.36       +/-0.00
50             509                                174                                0.34       +/-0.00
500            3832                               1623                               0.42       +/-0.00
5000           36665                              14117                              0.39       +/-0.00
50000          364886                             112373                             0.31       +/-0.00

		</pre>

		<script type="text/javascript">
		var show = true;
		function show_hide_deleted() {
			var to_change = document.getElementsByClassName('changed-deleted');
			for (var i = 0; i < to_change.length; ++i) {
				to_change[i].style.display = (show ? 'inline' : 'none');
			}

			show = !show;
		}

		</script>




</body></html>
