ulrik@kaizer.se/ log/ post/
C++ constexpr

Here is some fun with C++11's constexpr. It seems we can check substring containment at compile time. The following example works fine with GCC 4.6.1.

#include <iostream>
#include <array>

constexpr bool not_end(const char *s, const int n) {
        return s && s[n];
}

/* does `s` have `t` as prefix. Use offsets ns, nt */
constexpr bool str_prefix(const char *s, const char *t, const int ns, const int nt) {
        return (s == t) || !*(t + nt) || (*(s + ns) == *(t + nt) && (str_prefix(s, t, ns+1, nt+1)));
}

constexpr int contains1(const char *s, const char *needle, const int n) {
        return not_end(s,n) && (str_prefix(s, needle, n, 0) || contains1(s, needle,n+1));
}

constexpr int contains(const char *s, const char *needle) {
        return contains1(s, needle, 0);
}

const int x = contains("froogler", "oogle");

int main(void) {
        std::array<int, 10 * contains("hi there", "the")> a;
        std::array<int, 10 * contains("hi thre", "the")> b;
        std::cout << "Array size for a is " << a.size() << "\n";
        std::cout << "Array size for b is " << b.size() << "\n";
        std::cout << "x: " << x << "\n";
}

It compiles without warnings using the commandline:

g++ -Wall -std=c++0x -o constarray constarray.cc

And produces the following output:

Array size for a is 10
Array size for b is 0
x: 1

So, is this a legal part of C++11? Is it a good thing? It is at least a more readable compile-time language than template metaprogramming.

If you want to contact me, I'm @englabenny on twitter

Edit to add a Bonus: an implementation of foldr over initializer lists, see C++ constexpr foldr