Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constexpr function parameters as template arguments

Tags:

I am playing around with some toy code using c++11 to figure out a bit more about how things work. During this I came across the following issue that simplifies down to:

template <int x, int y> class add { public:     static constexpr int ret = x + y; };  constexpr int addFunc(const int x, const int y) {     return add<x,y>::ret; }  int main() {     const int x = 1;     const int y = 2;     cout << add<x,y>::ret << endl; // Works     cout << addFunc(1,2) << endl;  // Compiler error     return 0; } 

I'm using GCC 4.8.1 and the output is:
'x' is not a constant expression in template argument for type 'int'
'y' is not a constant expression in template argument for type 'int'

What exactly is the difference between the two ways I am trying to calculate add::ret? Both of these values should be available at compile time.

like image 372
Danny Avatar asked Oct 27 '14 07:10

Danny


People also ask

Can a function parameter be constexpr?

We allow annotating a function parameter with constexpr with the same meaning as a variable declaration: must be initialized with a constant expression. We add a new keyword, maybe_constexpr , that deduces whether the parameter is known at compile time.

Can you modify constexpr?

A const int var can be dynamically set to a value at runtime and once it is set to that value, it can no longer be changed. A constexpr int var cannot be dynamically set at runtime, but rather, at compile time. And once it is set to that value, it can no longer be changed.

Does constexpr improve performance?

Understanding constexpr Specifier in C++ constexpr is a feature added in C++ 11. The main idea is a performance improvement of programs by doing computations at compile time rather than run time.

Should I use constexpr everywhere?

Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.


2 Answers

If your purpose is just to shorten code a bit, in C++14 you can create variable template:

template <int x, int y> constexpr int addVar = x + y;  cout << addVar<5, 6> << endl; // Works with clang 3.5, fails on GCC 4.9.1 

GCC 5 will also support this.

like image 163
Anton Savin Avatar answered Oct 19 '22 00:10

Anton Savin


You tell the compiler, that addFunc would be a constexpr. But it depents on parameters, that are not constexpr itself, so the compiler already chokes on that. Marking them const only means you are not going to modify them in the function body, and the specific calls you make to the function are not considered at this point.

There is a way you can make the compiler understand you are only going to pass compile time constants to addFunc: Make the parameters a template parameters itself:

template <int x, int y> constexpr int addFunc() {     return add<x,y>::ret; } 

Then call as

cout << addFunc<1,2>() << endl; 
like image 40
Raoul Steffen Avatar answered Oct 19 '22 01:10

Raoul Steffen