<div class="gmail_quote">On Tue, Jul 24, 2012 at 7:23 PM, Howard Hinnant <span dir="ltr"><<a href="mailto:hhinnant@apple.com" target="_blank">hhinnant@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">On Jul 24, 2012, at 6:05 PM, Fernando Pelliccioni <<a href="mailto:fpelliccioni@gmail.com">fpelliccioni@gmail.com</a>> wrote:<br>
<br>
><br>
><br>
> On Sun, Jul 22, 2012 at 9:49 PM, Howard Hinnant <<a href="mailto:hhinnant@apple.com">hhinnant@apple.com</a>> wrote:<br>
> I'm playing with this code created by Scott Schurr and presented at C++Now:<br>
><br>
> <a href="http://cppnow.org/session/cpp11-new-tools-for-class-and-library-authors/" target="_blank">http://cppnow.org/session/cpp11-new-tools-for-class-and-library-authors/</a><br>
><br>
> #include <cstddef><br>
> #include <stdexcept><br>
><br>
> class str_const<br>
> {<br>
> const char* const p_;<br>
> const std::size_t sz_;<br>
> public:<br>
> template<std::size_t N><br>
> constexpr str_const(const char(&a)[N]) :<br>
> p_(a), sz_(N-1) {}<br>
><br>
> constexpr char operator[](std::size_t n)<br>
> {<br>
> return n < sz_ ? p_[n] : throw std::out_of_range("");<br>
> }<br>
><br>
> constexpr std::size_t size() { return sz_; }<br>
> };<br>
><br>
> template <class T = std::size_t><br>
> constexpr<br>
> inline<br>
> T<br>
> binary_const(str_const b, std::size_t n = 0, T x = 0)<br>
> {<br>
> return n == b.size() ? x :<br>
> b[n] == ',' ? binary_const<T>(b, n+1, x) :<br>
> b[n] == ' ' ? binary_const<T>(b, n+1, x) :<br>
> b[n] == '0' ? binary_const<T>(b, n+1, x*2) :<br>
> b[n] == '1' ? binary_const<T>(b, n+1, x*2+1) :<br>
> throw std::domain_error("Only '0', '1', ',', and ' ' may be used");<br>
> }<br>
><br>
> int main()<br>
> {<br>
> constexpr str_const test("Hi Mom!");<br>
> static_assert(test.size() == 7, "");<br>
> static_assert(test[6] == '!', "");<br>
> constexpr unsigned i = binary_const("1111,0000");<br>
> return i;<br>
> }<br>
><br>
> $ clang++ -std=c++11 -stdlib=libc++ -O3 test.cpp -S<br>
><br>
> Everything compiles and runs great (I know, I'm never happy). But when I inspect the assembly of main I see:<br>
><br>
> callq __Z12binary_constImET_9str_constmS0_<br>
> movl $240, %eax<br>
> popq %rbp<br>
> ret<br>
><br>
> Now returning 240 is the right answer. But why is binary_const being called at run time? Can't this call be elided because we know it is a constexpr function (without side effects) and that it is going to return the value 240 that we've already computed at compile time?<br>
><br>
> Howard<br>
><br>
> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
><br>
><br>
><br>
> Hello Howard,<br>
><br>
> What is the purpose of throwing an exception in a constexpr function?<br>
> Or rather... What are the implications of throwing in a constexpr function?<br>
<br>
</div></div>If you supply a non-constexpr argument that would cause the exception to be thrown, or if you assign the result to a non-constexpr object, then you will get the run time exception.<br>
<br>
If you are using the function to initialize a constxpr object, then you must be supplying constexpr arguments as well.<br>
And if you supply a constexpr argument that would cause the exception to be thrown (if the function were to be executed at run time), then you will get a compile-time failure along the lines of:<br>
<br>
test.cpp:183:24: error: constexpr variable 'i' must be initialized by a constant expression<br>
constexpr unsigned i = binary_const("11*11,0000");<br>
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
test.cpp:175:12: note: subexpression not valid in a constant expression<br>
<div class="im"> throw std::domain_error("Only '0', '1', ',', and ' ' may be used");<br>
</div> ^<br>
test.cpp:174:26: note: in call to 'binary_const({&"11*11,0000"[0], 10}, 2, 3)'<br>
<div class="im"> b[n] == '1' ? binary_const<T>(b, n+1, x*2+1) :<br>
</div> ^<br>
test.cpp:174:26: note: in call to 'binary_const({&"11*11,0000"[0], 10}, 1, 1)'<br>
test.cpp:183:28: note: in call to 'binary_const({&"11*11,0000"[0], 10}, 0, 0)'<br>
constexpr unsigned i = binary_const("11*11,0000");<br>
^<br>
1 error generated.<br>
<br>
So the purpose is for error checking, which will happen either at run time, or at compile time, depending on how the function is used.<br>
<span class="HOEnZb"><font color="#888888"><br>
Howard<br>
<br>
</font></span></blockquote></div><br><div><br></div><div><div>Howard, thank you very much for your explanation.</div><div>I thought that "throw" was the culprit.</div></div><div><br></div><div>Regards,</div><div>
Fernando.</div>