Are floating point calculations, which use compile-time constant integers, performed during compile-time or during run-time? For example, when is the division operation calculated in:
template <int A, int B>
inline float fraction()
{
return static_cast<float>(A) / B;
}
For something this simple, the compiler will probably do it at compile time. In fact, the compiler will probably do it at compile time even without templates, as long as all the values are known at compile time: i.e. if we have inline float fraction(int A, int B), it will probably do the division at compile time if we call fraction(1,2) .
If you want to force the compiler to do stuff at compile-time, you will have to use some template metaprogramming tricks, and I'm not sure you can get it to work with floating-point arithmetic at all. But here is a basic example of the technique:
// Something similarly simple that doesn't use floating-point ;)
template <int A, int B>
struct Product {
enum { value = A * B };
};
// Later:
... Product<3, 4>::value ...
I believe it is implementation defined, but most compilers will evaluate constant expressions at compile time. However even if yours does not the following modification:
template <int A, int B>
inline float fraction()
{
static const float f = static_cast<float>(A) / B;
return f ;
}
will at least ensure that the expression is evaluated just once if it is evaluated at runtime.
You should wait for gcc 4.6 with C++0x constexpr keyword implementation.
Your best bet is to look at the generated code - there is no guarantee that floating-point operations will be performed at compile time, but at higher optimisation levels they potentially could be, particularly for something simple like this.
(Some compilers might avoid doing this because for some architectures the floating point behaviour is configurable at runtime. The results for the operation performed at compile time could then potentially differ from those from the same operation performed at runtime.)
Neither the C or C++ standards require that constant expressions of any stripe be evaluated at compile time, but they do allow it. Most compilers released in the last 20 years will evaluate arithmetic expressions, so if not incurring a function call or inlining the code is important, keep it as simple as possble.
If the scope of these expressions is limited to a single file, you can always take advantage of the preprocessor and #define FRACTION(a,b) (float(a)/float(b)) for convenience. I don't recommend doing this in a header unless you have a good scheme to prevent polluting any file that #includes it.
Related
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++
constexpr
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?
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.
When I define a constexpr function, should I also declare it as noexcept? I imagine in the case where the arguments and usage satisfy the requirements for compile-time evaluation, the meaning of potential exceptions is moot. But it would apply as normal for cases when the function is evaluated at run time.
As a matter of practical concern, if the function is indeed simple, perhaps using built-in arithmetic or a cast, such that I expect the compiler can always inline the function and optimize across it, does it matter to the efficiency of the generated code if I leave off noexcept?
No, you should not.
"Cannot fail" and "can be evaluated at compile time" are orthogonal issues. For example, you want to write an integer power function, but you want to take the power as signed (because you believe that unsigned numbers should only be used for very special cases). Now you say you want to throw an exception if the power is negative. In C++14 you can write it like this:
constexpr int ipow(int base, int power) {
if (power < 0) throw std::domain_error("negative power");
int result = 1;
for (int i = 0; i < power; ++i) result *= base;
return result;
}
This function clearly isn't noexcept, but for non-negative arguments, you obviously can evaluate it at compile time. If you try it for negative arguments in a context where you need the result at compile time, you get a compile error, which should be fine.
I am reading about C++ templates and would like to contrast two different implementations of a function which computes sum from 0 to N.
Unfortunately, I have problems and would like to address a few questions through examples:
Code for naive sum:
#include <stdio.h>
template<int N>
struct Sum {
// Copied the implementation idea from Scott Meyers book
// "Effective C++". Is there a better way?
enum { value = N + Sum<N - 1>::value };
};
template<>
struct Sum<0> {
enum { value = 0 };
};
int main() {
// Works well in this case, but gives compilation error, if
// it's called with a larger value, such as 10000
// (error: template instantiation depth exceeds maximum of 900").
// How to improve the program properly, that it would
// not give compile time error?
printf("%d\n", Sum<100>::value);
}
Now my idea for an improvement is to use an accumulator:
template<int Acc, int N>
struct Sum {
enum { value = Sum<Acc + N, N - 1>::value };
};
// Is that an appropriate way of writing the base case?
template<int Acc>
struct Sum<Acc, 0> {
enum { value = Acc };
};
However, when compiled with simple g++ on Ubuntu OS:
int main() {
// Still gives the "depth exceeded" error.
printf("%d\n", Sum<0, 1000>::value);
}
Hence, my main concern is:
Does any modern c++ compiler support last call optimisation for
template metaprogramming? If yes, what is an appropriate way to write code for such optimisation?
Does any modern c++ compiler support last call optimisation for template metaprogramming? If yes, what is an appropriate way to write code for such optimisation?
No, and it wouldn't make sense. Template instantiations are not function calls... last/tail call optimisation has no relevance here. Unlike function calls, template instantiations are not transient with automatic variables to reclaim; rather, each template instantiation becomes a new type in the compiler's state.
The whole point of template metaprogramming is that all of these "calls" will be optimised out of your program; they are "executed" during the build.
That doesn't change the fact that there is an implementation-defined limit to the amount of recursion you can use during this process. This is the limit you've hit.
So, no, there's no "optimisation" to work around it.
Short answer: incorporating LCO is not worth the trouble.
Longer explanation:
C++ template meta programming is Turing Complete. In theory it would be possible to compute any computable function at compile time using only templates (if enough resources were given). LCO would make such computation more efficient.
That does not mean templates should be used for sophisticated computations. Run time is for that. C++ templates merely aid to avoid writing identical code.
In fact, doing complicated computation through templates is discouraged, because one has little compiler support. The preprocessor will only expand templated code into more code and that's it. No type checking, etc. is happening when processing templates.
So I think the designers of c++ have more interesting things to add in the language rather than optimise template meta programming. Maybe after 20 years we will have LCO support. Currently there is no.
Say I have a simple function that does something like this:
template<typename T>
T get_half(T a){
return 0.5*a;
}
this function will typically be evaluated with T being double or float.
The standard specifies that 0.5 will be a double (0.5f for float).
How can write the above code so that 0.5 will always be of type T so that there is no cast when evaluating either the product or the return?
What I want is 0.5 to be a constant of type T at compile time. The point of this question is that I want to avoid conversion at run time.
For example, if I write:
template<typename T>
T get_half(T a){
return T(0.5)*a;
}
Can I be absolutely sure that T(0.5) is evaluated at compile time?
if not, what would be the proper approach to accomplish this? I'm ok with using c++11 if that is needed.
Thank you in advance.
In c++11 I have a numeric_traits class something as follows (within a header file)
template<typename Scalar>
struct numeric_traits{
static constexpr Scalar one_half = 0.5;
//Many other useful constants ....
};
so within my code I would use this as:
template<typename T>
T get_half(T a){
return numeric_traits<T>::one_half*a;
}
This does what I want i.e. 0.5 is resolved at compile time with the precision I need and no casts happen at run-time. However the downsides are:
I need to modify numeric_traits every time I need a new constant
The sintax is probably too verbosely annoying? (not a big issue really, of course)
It'd be nice maybe have something like: constant(0.5) which resolves to T type at run-time.
Thank you in advance again.
There isn't and cannot be any way of forcing constants to never be computed at run-time, because some machines simply don't have a single instruction that can load all possible values of a type. For instance, machines may only have a 16-bit load constant instruction, where 0x12345678 would need to be computed, at run-time, as 0x1234 << 16 | 0x5678. Alternatively, such a constant might be loaded from memory, but that could be an even more costly operation than computing it.
You need to trust your compiler a little bit. On systems where it is feasible, any compiler that has any amount of optimisation at all will translate T(0.5) the same way it will translate 0.5f, assuming T is float. And 0.5f will be computed in the most sensible way for your platform. That might involve loading it as a constant, or that might involve computing it. Or who knows, your compiler might change T(0.5)*a to a/2 if that gives the same results.
In your question you give an example of adding a numeric_traits helper class. This, IMO, is overkill. In the extremely unlikely case that constexpr makes a difference, you can just write
template <typename T>
T get_half(T a) {
constexpr T half = 0.5;
return half * a;
}
However, this still does more harm than good, in my opinion: your get_half can now no longer be used with non-literal types. It requires the type to support conversions from double in constant expressions. Suppose you have an arbitrary-precision rational type, written without constexpr in mind. Now your get_half can not be used, because the initialisation constexpr T half = 0.5; is invalid, even if 0.5 * a might otherwise have compiled.
This is the case even with your numeric_traits helper class; it's not invalid just because I moved it into the function body.
I'm quite confused with the new keyword constexpr of C++2011. I would like to know where to use constexpr and where to use templates metaprogramming when I code compile-time functions (especially maths functions). For example if we take an integer pow function :
// 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 the 2nd and 3rd functions equivalent ?
What is the best solution ? Does it produce 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 : code modified to include specialization for templates
I probably shouldn't be answering a template metaprogramming question this late. But, here I go.
Firstly, constexpr isn't implemented in Visual Studio 2012. If you want to develop for windows, forget about it. I know, it sucks, I hate Microsoft for not including it.
With that out of the way, there's lots of things you can declare as constant, but they aren't really "constant" in terms of "you can work with them at compile time." For instance:
const int foo[5] = { 2, 5, 1, 9, 4 };
const int bar = foo[foo[2]]; // Fail!
You'd think you could read from that at compile time, right? Nope. But you can if you make it a constexpr.
constexpr int foo[5] = { 2, 5, 1, 9, 4 };
constexpr int bar = foo[foo[2]]; // Woohoo!
Constexpr's are really good for "constant propagation" optimization. What that means is if you have a variable X, that is declared at compile time based on some condition (perhaps metaprogramming), if it is a constexpr then the compiler knows it can "safely" use it when doing optimization to, say, remove instructions like a = (X * y); and replace them with a = 0; if X evaluated to 0 (and other conditions are met).
Obviously this is great because for many mathematical functions, constant propagation can give you an easy (to use) premature optimization.
Their main use, other than rather esoteric things (such as enabling me to write a compile-time byte-code interpreter a lot easier), is to be able to make "functions" or classes that can be called and used both at compile-time and at runtime.
Basically they just sort of fill a hole in C++03 and help with optimization by the compiler.
So which of your 3 is "best"?
2 can be called at run-time, whereas the others are compile-time only. That's pretty sweet.
There's a bit more to it. Wikipedia gives you a very basic summary of "constexpr allows this," but template metaprogramming can be complicated. Constexpr makes parts of it a lot easier. I wish I had a clear example for you other than say, reading from an array.
A good mathematical example, I suppose, would be if you wanted to implement a user-defined complex number class. It would be an order of magnitude more complex to code that with only template metaprogramming and no constexpr.
So when should you not use constexpr? Honestly, constexpr is basically "const except MORE CONST." You can generally use it anywhere you'd use const, with a few caveats such as how when called during runtime a function will act non-const if its input isn't const.
Um. OK, that's all for now. I'm too overtired to say more. I hope i was helpful, feel free to downvote me if I wasn't and I'll delete this.
1st and 3rd are incorrect. Compiler will try instantiate tpow<N-1> before it will evaluate (N>0) ?, and you will get infinite template recursion. You need specialisation for N==1 (or ==0) to make it work. 2nd will work for xknown at compile time and run time.
Added after your specialization for ==0 edit. Now all function will work for compile time or run time x. 1st will always return non constexpr value. 2nd and 3rd will return constexpr if x and N are constexpr. 2nd even work if N is not constexpr, other need constexpr N (so, 2nd and 3rd are not equivalent).
The constexpr is used in two cases. When you write int N=10;, value of N is known at compile time but it is not constexpr and can not used for example as template argument. Keyword constexpr explicitly tells compiler that N is safe to use as compile time value.
Second use is as constexpr functions. They use subset of C++ to conditionally produce constexpr values and can dramatically simplify equivalent template functions. One detriment of constexpr functions is that you have no guaranteed compile time evaluation -- compiler can chose to do evaluation in in run time. With templated implementation you are guaranteed compile time evaluation.