3

I'm trying to understand the code:

#include <iostream>
#include <stdexcept>

// constexpr functions use recursion rather than iteration
constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}

// literal class
class conststr {
    const char * p;
    std::size_t sz;
 public:
    template<std::size_t N>
    constexpr conststr(const char(&a)[N]) : p(a), sz(N-1) {}
    // constexpr functions signal errors by throwing exceptions from operator ?:
    constexpr char operator[](std::size_t n) const {
        return n < sz ? p[n] : throw std::out_of_range("");
    }
    constexpr std::size_t size() const { return sz; }
};

constexpr std::size_t countlower(conststr s, std::size_t n = 0,
                                             std::size_t c = 0) {
    return n == s.size() ? c :
           s[n] >= 'a' && s[n] <= 'z' ? countlower(s, n+1, c+1) :
           countlower(s, n+1, c);
}

// output function that requires a compile-time constant, for testing
template<int n> struct constN {
    constN() { std::cout << n << '\n'; }
};

int main()
{
    std::cout << "4! = " ;
    constN<factorial(4)> out1; // computed at compile time

    volatile int k = 8; // disallow optimization using volatile
    std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time

    std::cout << "Number of lowercase letters in \"Hello, world!\" is ";
    constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
}

What is the parameter

const char(&a)[N]

? I don't understand it.. seems like a reference to an array.. and what's the point in passing it to a constexpr constructor?

3
  • Yes, it is a reference to an array of fixed size. And because its size is defined by a template, it has the result of defining a (constexpr) constructor for each size of array that you might pass (with the end result that sz is set to the constant size of the array you passed). So that's fine, but whether constexpr is actually valid for constructors is something I'm not sure about. Commented Jun 8, 2013 at 22:41
  • probably duplicate: stackoverflow.com/questions/6376000/… Commented Jun 8, 2013 at 22:44
  • OK, some quick searches tell me that constexpr constructors are indeed valid. In effect they allow the constructor to be called at compile time, leaving just something which behaves like thing a={0,1,2} behind, pretty much as you'd expect. Commented Jun 8, 2013 at 22:44

2 Answers 2

5

The parameter const char(&a)[N] is a reference to an array.

The point of it is that it allows the compiler to deduce the length of the array. Without the reference, const char a[N] as parameter would be equivalent to const char* a which doesn't allow the template parameter N to be deduced.

Sign up to request clarification or add additional context in comments.

4 Comments

That is not the only point. The array is immutable. Plain char(&a)[N] wouldn't do here.
Nor would char* a. But that's an orthogonal issue, and there's no indication that David Kermin had any problems with the const.
It is not an orthogonal issue. The constexprs wouldn't work with a mutable, fixed size array.
The deduction of N is orthogonal to the whole thing being constexpr. It would work exactly the same way on a non-constexpr template.
2

This is (along with the template<std::size_t N> part), a way to get the size of a constant string, so you can do:

conststr hello("Hello, World!"); 

and later:

size_t s = hello.size(); 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.