3

On this site, they give this example of a literal class:

#include <iostream>
#include <stdexcept>

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 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 << "the number of lowercase letters in \"Hello, world!\" is ";
    constN<countlower("Hello, world!")>(); // implicitly converted to conststr
}

The program results in the output

the number of lowercase letters in "Hello, world!" is 9

But I don't understand one part of this program. Namely, this line here:

constexpr conststr(const char(&a)[N]) : p(a), sz(N - 1) {}

const char(&a)[N], what does this syntax exactly mean? Does it have a name?

John Burger
  • 3,662
  • 1
  • 13
  • 23
Erkaman
  • 75
  • 1
  • 7

1 Answers1

5

The code const char(&a)[N] needs parentheses to say "a is a reference: to an array of N const chars".

Without the parentheses, you'd have const char &a[N] - which would be "a is an array of N const char references", which isn't allowed.

That's why I prefer typedefs, to make those kinds of things more clear:

typedef const char ArrayN[N];

ArrayN &a = ...; // Whatever you want 'a' to refer to
John Burger
  • 3,662
  • 1
  • 13
  • 23
  • note that you *can't* use a typedef in the situation shown. You could use an alias template, such as `template using ArrayN = const char[N];`, giving `constexpr conststr(ArrayN& a)` – Caleth Mar 11 '20 at 16:05
  • @Caleth I admit my example was incomplete [now amplified] - but the `typedef` was certainly not incorrect. In fact, the `typedef` was used _exactly_ as it was intended to be used... – John Burger Mar 11 '20 at 16:14
  • There's no place for the typedef when `N` is a template parameter of a function – Caleth Mar 11 '20 at 16:16
  • @Caleth Ah, you're right. This was a resurrection from a few years ago, and I forgot the original premise. However, the `typedef` example is still relevant - just not in this case! (I wonder if the language will allow it in the future?) – John Burger Mar 11 '20 at 16:23