{"id":1206,"date":"2015-10-13T08:47:49","date_gmt":"2015-10-13T15:47:49","guid":{"rendered":"http:\/\/www.elbeno.com\/blog\/?p=1206"},"modified":"2015-10-15T08:55:55","modified_gmt":"2015-10-15T15:55:55","slug":"experimenting-with-constexpr","status":"publish","type":"post","link":"https:\/\/www.elbeno.com\/blog\/?p=1206","title":{"rendered":"Experimenting with constexpr"},"content":{"rendered":"<p>Since seeing Scott Schurr at C++Now in Aspen and hearing <a href=\"https:\/\/www.youtube.com\/watch?v=fZjYCQ8dzTc\">his<\/a> <a href=\"https:\/\/www.youtube.com\/watch?v=qO-9yiAOQqc\">talks<\/a> about <code>constexpr<\/code>, it&#8217;s been on my list of things to try out, and recently I got around to it. With the release of Visual Studio 2015, Microsoft&#8217;s compiler now finally supports C++11 style <code>constexpr<\/code> (modulo some minor issues), so it&#8217;s a good time to jump in.<\/p>\n<p><strong>Doing things the hard way<\/strong><\/p>\n<p>Now, I have no expectation that MS will provide for C++14 <code>constexpr<\/code> any time soon, since (as I understand it) it requires a fairly dramatic rework of the compiler front end. So although C++14&#8217;s relaxed <code>constexpr<\/code> is much easier to use than C++11&#8217;s relatively draconian version, I decided to stick as much as possible to C++11 to see what I could do. This basically means:<\/p>\n<ul>\n<li>Functions are limited to a single <code>return<\/code> statement<\/li>\n<li>Constructor bodies are empty &#8211; everything must be done in the initialization list<\/li>\n<\/ul>\n<p>But I can do conditionals with the ternary operator, and I can call functions. That means in theory I can do anything! I like functional programming!<\/p>\n<p>Scott&#8217;s talk covers three broad application areas of <code>constexpr<\/code>: floating-point computations, parsing and containers. So I started at the beginning.<\/p>\n<p>I decided to put everything in the <code>cx<\/code> namespace, and make use of a trick I learned from Scott. One of the snags with <code>constexpr<\/code> is that it can be at the compiler&#8217;s discretion. Let&#8217;s say you write a <code>constexpr<\/code> function, and call it. Unless you use the result in a context that is required at compile time (such as a non-type template argument, array size, or assigned to a <code>constexpr<\/code> variable), the compiler is free <em>not<\/em> to do the work at compile time, but instead generate a normal runtime function. And in my experience, compilers aren&#8217;t aggressive about doing work at compile time.<\/p>\n<p>From one point of view this is somewhat desirable &#8211; or at least, we want <code>constexpr<\/code> functions to be able to do double duty as compile-time and runtime functions. Well, that&#8217;s a stated goal, but as we shall see, writing C++11-friendly <code>constexpr<\/code> functions sometimes results in formulations that are very different from what we&#8217;d usually expect\/want at runtime. But let&#8217;s assume that I write a nice <code>constexpr<\/code> function:<\/p>\n<pre lang=\"cpp\">\r\nconstexpr float abs(float x)\r\n{\r\n  return x >= 0 ? x : -x;\r\n}\r\n<\/pre>\n<p>Now what if I make a mistake using this? What if I call this function and forget to use the result in a <code>constexpr<\/code> variable? The compiler&#8217;s going to be quite happy to emit the function, and I will end up with runtime computation that I don&#8217;t want.<\/p>\n<p><strong>Avoiding accidental runtime work<\/strong><\/p>\n<p>There&#8217;s no way I know of at compile time to insist that the compiler stay in <code>constexpr<\/code>-land. But we can at least turn a runtime problem into a link-time error with a little trick:<\/p>\n<pre lang=\"cpp\">\r\nnamespace err {\r\n  namespace {\r\n    extern const char* abs_runtime_error;\r\n  }\r\n}\r\n\r\nconstexpr float abs(float x)\r\n{\r\n  return x >= 0 ? x :\r\n    x < 0 ? -x :\r\n    throw err::abs_runtime_error;\r\n}\r\n<\/pre>\n<p>This makes use of a couple of features of <code>constexpr<\/code>. First, <code>throw<\/code> is not allowed in <code>constexpr<\/code> functions (because what could it mean to throw an exception at compile time? Madness). But that doesn't matter, because <code>constexpr<\/code> functions are effectively evaluated in a C++ interpreter, so as long as we never trigger the condition that causes evaluation of the <code>throw<\/code>, we're OK. This compile-time interpreter also has a lot fewer features than the normal compiler that we're used to, including (at least at time of writing) things like warnings for unreachable code and conditional expressions always being true, so we can even write things like:<\/p>\n<pre lang=\"cpp\">\r\nconstexpr float myFunc(float x)\r\n{\r\n  return true ? x :\r\n    throw some_error;\r\n}\r\n<\/pre>\n<p>And the compiler won't make a sound.<\/p>\n<p><strong>The <code>throw<\/code> pattern<\/strong><\/p>\n<p>So what's actually happening here? We're getting two forms of protection. First, we can use this to enforce the domain, as we might with a square root function:<\/p>\n<pre lang=\"cpp\">\r\nnamespace err {\r\n  namespace {\r\n    extern const char* sqrt_error;\r\n  }\r\n}\r\n\r\nconstexpr float sqrt(float x)\r\n{\r\n  return x >= 0 ? sqrt_impl(x) :\r\n    throw sqrt_error;\r\n}\r\n<\/pre>\n<p>If we accidentally pass a negative number to <code>sqrt<\/code> here, it will try to evaluate <code>throw<\/code> in a <code>constexpr<\/code> function and we'll get a compile error. So that's nice.<\/p>\n<p>The second, more insidious error that we avoid is the one where we accidentally turn a compile-time function into a runtime one. If we call <code>sqrt<\/code> without (for example) assigning the result to a <code>constexpr<\/code> variable, and the compiler emits <code>sqrt<\/code> as a runtime function, the linker will fail trying to find <code>sqrt_error<\/code>. A link error isn't quite as good as a compile error, but it's a lot better than a runtime problem that might not even be discovered!<\/p>\n<p>The final oddity here arises when you consider that this code might be in a header. Since <code>constexpr<\/code> functions are (we hope) computed at compile time, they are implicitly <code>inline<\/code>, so that's OK. But perhaps the stranger thing is that we have a symbol in an anonymous namespace in a header. This, by the way, is <a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/CppCoreGuidelines.md#-sf21-dont-use-an-unnamed-anonymous-namespace-in-a-header\">called out<\/a> in the <a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\">ISO C++ Core Guidelines<\/a> as a no-no: \"It is almost always a bug to mention an unnamed namespace in a header file.\" But in this case, we don't want the user to be able to define the symbol, and the potential for ODR-violations\/multiple definitions isn't there - the symbol is never <em>supposed<\/em> to be defined or used. Maybe we've found the one reason for that \"almost\".<\/p>\n<p>So those are some of the basics of building <code>constexpr<\/code> machinery. Next: my dive into <a href=\"https:\/\/www.elbeno.com\/blog\/?p=1211\">floating-point maths at compile time<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since seeing Scott Schurr at C++Now in Aspen and hearing his talks about constexpr, it&#8217;s been on my list of things to try out, and recently I got around to it. With the release of Visual Studio 2015, Microsoft&#8217;s compiler now finally supports C++11 style constexpr (modulo some minor issues),&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22],"tags":[],"class_list":["post-1206","post","type-post","status-publish","format-standard","hentry","category-cpp"],"_links":{"self":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1206","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1206"}],"version-history":[{"count":7,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1206\/revisions"}],"predecessor-version":[{"id":1304,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1206\/revisions\/1304"}],"wp:attachment":[{"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1206"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elbeno.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}