Constexpr vs template for math functions compilation time?

I am very confused by the new constexpr keyword from C ++ 2011. I would like to know where to use constexpr and where to use template metaprogramming when I code compile-time functions (especially mathematical functions). For example, if we take the integer function pow:

// 1 : template <int N> inline double tpow(double x) { return x*tpow<N-1>(x); } template <> inline double tpow<0>(double x) { return 1.0; } // 2 : constexpr double cpow(double x, int N) { return (N>0) ? (x*cpow(x, N-1)) : (1.0); } // 3 : template <int N> constexpr double tcpow(double x) { return x*tcpow<N-1>(x); } template <> constexpr double tcpow<0>(double x) { return 1.0; } 

Are 2nd and 3rd functions equivalent? What is the best solution? Does it get the same result:

  • if x is known at compile time
  • if x is not known at compile time

When to use constexpr and when to use template metaprogramming?

EDIT 1: changed code to enable specialization for templates

+8
c ++ c ++ 11 templates metaprogramming constexpr
source share
2 answers

I probably shouldn't answer the question of template metaprogramming this late. But, here I go.

Firstly, constexpr is not implemented in Visual Studio 2012. If you want to develop for Windows, forget about it. I know this sucks; I hate Microsoft for not including it.

With this you can say that there are many things that you can declare constant, but they are not "permanent" in terms of "you can work with them during compilation." For example:

 const int foo[5] = { 2, 5, 1, 9, 4 }; const int bar = foo[foo[2]]; // Fail! 

Do you think you could read this at compile time, right? Nope. But you can do it constexpr.

 constexpr int foo[5] = { 2, 5, 1, 9, 4 }; constexpr int bar = foo[foo[2]]; // Woohoo! 

Constexpr is really good at optimizing "continuous distribution." This means that if you have an X variable declared at compile time based on some condition (possibly metaprogramming), if it is constexpr, then the compiler knows that it can “safely” use it when performing optimization, for example, when deleting such instructions like a = (X * y); and replace them with a = 0; if X is evaluated to 0 (and other conditions are satisfied).

Obviously, this is great, because for many mathematical functions, constant propagation can give you easy (use) premature optimization.

Their main use, in addition to quite esoteric things (for example, allowing me to write a bytecode interpreter in the compiler is much simpler), is to be able to create "functions" or classes that can be called and used both during compilation and during fulfillment.

Basically, they just fill a hole in C ++ 03 and help optimize the compiler.

So which of your 3s is "better"?

2 can be called at run time, while others can only be called at compile time. It is very nice.

There is a bit more. Wikipedia gives you a very general summary of “constexpr allows this,” but metaprogramming a template can be tricky. Constexpr greatly facilitates its parts. I'm sorry that I did not have a clear example for you, except, say, from an array.

A good mathematical example, I suppose, would be if you wanted to implement a custom complex class of numbers. It would be an order of magnitude more difficult to code this with just metaprogramming the template and without constexpr.

So when should you not use constexpr? Honestly, constexpr is basically "const, except MORE CONST". Usually, you can use it wherever you use const, with a few warnings, for example, how, when called at run time, a function will act unstable if its input is not const.

Um. All right for now. I was too overdoing to say more. Hope I was helpful, feel free to if I don’t, and I will remove it.

+8
source share

1st and 3rd are wrong. tpow<N-1> compiler try to instantiate tpow<N-1> before it evaluates (N>0) ? and you get infinite recursion of the template. In order for it to work, you need the specialization N==1 (or ==0 ). 2nd will work for x , known at compile time and runtime.

Added after your specialization for editing ==0 . Now the whole function will work for compile time or runtime x . 1st will always return a non constexpr value. 2nd and 3rd will return constexpr if x and N are constexpr. The 2nd one even works if N not constexpr, the other one needs constexpr N (so the 2nd and 3rd are not equivalent).

Constexpr is used in two cases. When you write int N=10; , the value of N is known at compile time, but it is not constexpr and cannot be used, for example, as an argument to a template. The constexpr keyword explicitly tells the compiler that N safe to use as a compile-time value. The second use is constexpr functions. They use a subset of C ++ to conditionally create constexpr values ​​and can greatly simplify equivalent template functions. One of the drawbacks of constexpr functions is that you do not have a guaranteed estimate of compilation time - the compiler can perform an evaluation at runtime. When using templates, you are guaranteed an estimate of the compilation time.

+1
source share

All Articles