# [cfe-dev] Question on constexpr

Howard Hinnant hhinnant at apple.com
Tue Jul 24 15:23:17 PDT 2012

```On Jul 24, 2012, at 6:05 PM, Fernando Pelliccioni <fpelliccioni at gmail.com> wrote:

>
>
> On Sun, Jul 22, 2012 at 9:49 PM, Howard Hinnant <hhinnant at apple.com> wrote:
> I'm playing with this code created by Scott Schurr and presented at C++Now:
>
> http://cppnow.org/session/cpp11-new-tools-for-class-and-library-authors/
>
> #include <cstddef>
> #include <stdexcept>
>
> class str_const
> {
>     const char* const p_;
>     const std::size_t  sz_;
> public:
>     template<std::size_t N>
>         constexpr str_const(const char(&a)[N]) :
>            p_(a), sz_(N-1) {}
>
>     constexpr char operator[](std::size_t n)
>     {
>         return n < sz_ ? p_[n] : throw std::out_of_range("");
>     }
>
>     constexpr std::size_t size() { return sz_; }
> };
>
> template <class T = std::size_t>
> constexpr
> inline
> T
> binary_const(str_const b, std::size_t n = 0, T x = 0)
> {
>     return n == b.size() ? x :
>            b[n] == ',' ? binary_const<T>(b, n+1, x) :
>            b[n] == ' ' ? binary_const<T>(b, n+1, x) :
>            b[n] == '0' ? binary_const<T>(b, n+1, x*2) :
>            b[n] == '1' ? binary_const<T>(b, n+1, x*2+1) :
>            throw std::domain_error("Only '0', '1', ',', and ' ' may be used");
> }
>
> int main()
> {
>     constexpr str_const test("Hi Mom!");
>     static_assert(test.size() == 7, "");
>     static_assert(test[6] == '!', "");
>     constexpr unsigned i = binary_const("1111,0000");
>     return i;
> }
>
> \$ clang++ -std=c++11 -stdlib=libc++ -O3  test.cpp -S
>
> Everything compiles and runs great (I know, I'm never happy).  But when I inspect the assembly of main I see:
>
>         callq   __Z12binary_constImET_9str_constmS0_
>         movl    \$240, %eax
>         popq    %rbp
>         ret
>
> 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?
>
> Howard
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
>
> Hello Howard,
>
> What is the purpose of throwing an exception in a constexpr function?
> Or rather... What are the implications of throwing in a constexpr function?

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.

If you are using the function to initialize a constxpr object, then you must be supplying constexpr arguments as well.
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:

test.cpp:183:24: error: constexpr variable 'i' must be initialized by a constant expression
constexpr unsigned i = binary_const("11*11,0000");
^   ~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:175:12: note: subexpression not valid in a constant expression
throw std::domain_error("Only '0', '1', ',', and ' ' may be used");
^
test.cpp:174:26: note: in call to 'binary_const({&"11*11,0000"[0], 10}, 2, 3)'
b[n] == '1' ? binary_const<T>(b, n+1, x*2+1) :
^
test.cpp:174:26: note: in call to 'binary_const({&"11*11,0000"[0], 10}, 1, 1)'
test.cpp:183:28: note: in call to 'binary_const({&"11*11,0000"[0], 10}, 0, 0)'
constexpr unsigned i = binary_const("11*11,0000");
^
1 error generated.

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.

Howard

```