What is compile time function in C++?

Viewed 5090

I've searched this question here(on SO), and as far as I know all questions assume what is compile time functions, but it is almost impossible for a beginner to know what that means, because resources to know that is quite rare.

I have found short wikipedia article which shows how to write incomprehensible code by writing never-seen-before use of enums in C++, and a video which is about future of it, but explains very little about that.

It seems to me that there are two ways to write compile time function in C++

  1. constexpr
  2. template<>

I've been through a short introduction of both of them, but I have no idea how they pop up here.

Can anyone explain compile time function with a sufficiently good example such that it encompasses most relevent features of it?

2 Answers

In cpp, as mentioned by you, there are two ways of evaluating a code on compile time - constexpr functions and template metaprogramming.

There are a few differences between those solutions. The template option is older and therefore supported by wider range of compilers. Additionaly templates are guaranteed to be evaluated in compile time while constexpr is somewhat like inline - it only suggests compiler that it is possible to do work while compiling. And for templates the arguments are usually passed via template parameters list while constexpr functions take arguments as regular functions (which they actually are). The constexpr functions are better in a manner that they can be called as regular functions in runtime.

Now the similarities - it must be possible for their parameters to be evaluated at compile time. So they must be either a literal or result of other compile-time function.

Having said all that let's look at compile time max function:

template<int a, int b>
struct max_template {
    static constexpr int value = a > b ? a : b;
};

constexpr int max_fun(int a, int b) {
    return a > b ? a : b;
}

int main() {
    int x = 2;
    int y = 3;
    int foo = max_fun(3, 2); // can be evaluated at compile time
    int bar = max_template<3, 2>::value; // is surely evaluated at compile time
//  won't compile without compile-time arguments  
//  int bar2 = max_template<x, y>::value; // is surely evaluated at compile time
    int foo = max_fun(x, y); // will be evaluated at runtime
    return 0;
}

A "compile time function" as you have seen the term used is not a C++ construct, it's just the idea of computing stuff (hence, function) at compile-time (as opposed to computing at runtime or via a separate build tool outside the compiler). C++ makes this possible in several ways, of which you have found two:

  • Templates can indeed be used to compute arbitrary stuff, a set of techniques called "template metaprogramming". That's mostly by accident as they weren't designed for this purpose at all, hence the crazy syntax and struggles with old compilers. But in C++03 and before, that's all we had.

  • constexpr has been added in C++11 after seeing the need for compile-time calculations, and brings them back into somewhat saner territory. Its toolbelt has been expanding ever since, allowing more and more normal-looking code to be run at compile-time by just tacking a constexpr in the right place.

One could also mention macro metaprogramming, of which Boost.Preprocessor is a good example. But it's even more wonky and abhorrently arcane than old-school template metaprogramming, so you probably don't want to use it if you have a choice.

Related