[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




More information about the cfe-dev mailing list