How to pass a pointer to const int in a recursive call. I am using the following code format to calculate Fibonacci recursively, but am getting the error:
error: lvalue required as unary '&' operand**
#include <iostream>
void fun(const int *n)
{
fun( &(*n-1) ); // it is giving error.
}
int main()
{
const int n = 4;
fun(&n);
}
You would have to use another variable then, to which you assign the decremented const variable: you simply can't pass a decreased value of a const variable, since by definition, it is not modifiable neither by increment or decrement.
#include <iostream>
void fun2 (const int *n)
{
std::cout << *n << std::endl;
}
void fun1(const int *n)
{
int x = *n-1;
fun2( &x );
}
int main()
{
const int n = 4;
fun1(&n);
}
as #nastor pointed out in comment using local variable problem solved.
#include <iostream>
void fun2 (const int *n)
{
std::cout << *n << std::endl;
}
void fun1(const int *n)
{
int x = *n-1;
fun2( &x );
}
int main()
{
const int n = 4;
fun1(&n);
}
void fun(const int *n)
{
fun( &(*n-1) ); // it is giving error.
}
You already passed a pointer, so you don't need to use the & as this would create a pointer from the pointer. Just pass the pointer. If you don't want to modifiy the parent value, then you don't need a pointer.
void fun(int n)
{
if (!n)
return;
fun(n-1);
}
int main()
{
const int n = 4;
fun(n);
}
All answers are already given and correct.
Unrelated to the level of the question, I will add the fastest possible solution for those who are interested in high speed Fibonacci number retrieval.
We simply do a compile time pre calculation of all Fibonacci numbers that fit into a 64 bit value. And then use a simple look up mechanism to get the value.
One important property of the Fibonacci series is that the values grow strongly exponential. So, all existing build in integer data types will overflow rather quickly.
With Binet's formula you can calculate that the 93rd Fibonacci number is the last that will fit in a 64bit unsigned value.
And calculating 93 values during compilation is a really simple task and does not waste that much space in the executable.
We will first define the default approach for calculation a Fibonacci number as a constexpr function:
// Constexpr function to calculate the nth Fibonacci number
constexpr unsigned long long getFibonacciNumber(size_t index) noexcept {
unsigned long long f1{ 0ull }, f2{ 1ull }, f3{};
while (index--) { f3 = f2 + f1; f1 = f2; f2 = f3; }
return f2;
}
With that, Fibonacci numbers can easily be calculated at compile time. Then, we fill a std::array with all Fibonacci numbers. We use also a constexpr function and make it a template with a variadic parameter pack.
We use std::index_sequence to create a Fibonacci number for indices 0,1,2,3,4,5, ....
That is straigtforward and not complicated:
// Some helper to create a constexpr std::array initilized by a generator function
template <typename Generator, size_t ... Indices>
constexpr auto generateArrayHelper(Generator generator, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<Generator>()(size_t{})), sizeof...(Indices) > { generator(Indices)... };
}
This function will be fed with an index sequence 0,1,2,3,4,... and a generator function and return a std::array<return type of generator function, ...> with the corresponding numbers, calculated by the generator.
We know that we can store maximum 93 values. And therefore we make a next function, that will call the above with the index sequence 1,2,3,4,...,92,93, like so:
template <size_t Size, typename Generator>
constexpr auto generateArray(Generator generator) {
return generateArrayHelper(generator, std::make_index_sequence<Size>());
}
And now, finally,
constexpr auto FibonacciNumber = generateArray<MaxArraySize64BitFibonacci>(getFibonacciNumber);
will give us a compile-time std::array<unsigned long long, 93> with the name FibonacciNumber containing all Fibonacci numbers. And if we need the i'th Fibonacci number, then we can simply write FibonacciNumber [i]. There will be no calculation at runtime.
I do not think that there is a faster way to calculate the n'th Fibonacci number.
Please see the complete program below:
#include <iostream>
#include <utility>
#include <array>
// All done during compile time -------------------------------------------------------------------
constexpr unsigned long long getFibonacciNumber(size_t index) noexcept {
unsigned long long f1{ 0ull }, f2{ 1ull }, f3{};
while (index--) { f3 = f2 + f1; f1 = f2; f2 = f3; }
return f2;
}
// Some helper to create a constexpr std::array initilized by a generator function
template <typename Generator, size_t ... Indices>
constexpr auto generateArrayHelper(Generator generator, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<Generator>()(size_t{})), sizeof...(Indices) > { generator(Indices)... };
}
template <size_t Size, typename Generator>
constexpr auto generateArray(Generator generator) {
return generateArrayHelper(generator, std::make_index_sequence<Size>());
}
constexpr size_t MaxArraySize64BitFibonacci = 93;
// This is the definition of a std::array<unsigned long long, 93> with all Fibonacci numbers in it
constexpr auto FibonacciNumber = generateArray<MaxArraySize64BitFibonacci>(getFibonacciNumber);
// End of: All done during compile time -----------------------------------------------------------
// Some debug test driver code
int main() {
for (const auto f : FibonacciNumber) std::cout << f << ' '; std::cout << '\n';
return 0;
}
By the way. The generateArray fucntionality will of course also work with other generator functions.
If you need for example triangle numbers, then you could use:
constexpr size_t getTriangleNumber(size_t row) noexcept {
size_t sum{};
for (size_t i{ 1u }; i <= row; i++) sum += i;
return sum;
}
and
constexpr auto TriangleNumber = generateArray<100>(getTriangleNumber);
would give you a compile time calculated constexpr std::array<size_t, 100>
So, a rather flexible helper.
Developed and tested with Microsoft Visual Studio Community 2019, Version 16.8.2.
Additionally compiled and tested with clang11.0 and gcc10.2
Language: C++17
Related
I want to use constexpr, compile time generated std::arrays for fast value-lookup instead of lengthy runtime calculations. For that I drafted a templated constexprfunction that will be executed at compile time.
Please see the following example code, which allows for ultrafast access to Triangle and Fibonacci numbers and factorials.
#include <iostream>
#include <utility>
#include <array>
constexpr size_t ArraySize = 20u;
// Some generator functions -------------------------------------------------------------
constexpr size_t getTriangleNumber(size_t row) noexcept {
size_t sum{};
for (size_t i{ 1u }; i <= row; i++) sum += i;
return sum;
}
constexpr unsigned long long getFibonacciNumber(size_t index) noexcept {
unsigned long long f1{ 0ull }, f2{ 1ull }, f3{};
while (index--) { f3 = f2 + f1; f1 = f2; f2 = f3; }
return f2;
}
constexpr unsigned long long getFactorial(size_t index) noexcept {
unsigned long long result{ 1 };
while (index > 0) { result *= index; --index; }
return result;
}
// Generate a std::array with n elements of a given type and a generator function -------
template <typename DataType, DataType(*generator)(size_t), size_t... ManyIndices>
constexpr auto generateArray(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<DataType, sizeof...(ManyIndices)>{ { generator(ManyIndices)... } };
}
// The arrays ---------------------------------------------------------------------------
constexpr auto TriangleNumber = generateArray<size_t, getTriangleNumber>(std::make_integer_sequence<size_t, ArraySize>());
constexpr auto FibonacciNumber = generateArray<unsigned long long, getFibonacciNumber>(std::make_integer_sequence<size_t, ArraySize>());
constexpr auto Factorial = generateArray<unsigned long long, getFactorial>(std::make_integer_sequence<size_t, ArraySize>());
// Some debug test driver code
int main() {
for (const auto t : TriangleNumber) std::cout << t << ' '; std::cout << '\n';
for (const auto f : FibonacciNumber) std::cout << f << ' '; std::cout << '\n';
for (const auto f : Factorial) std::cout << f << ' '; std::cout << '\n';
return 0;
}
As you can see. The template uses a parameter "DataType". In my opinion this is redundant. This is always the return type of the generator function. And it will also determine the data type for the std::array
So, how can we eliminate this redundancy and just use the type given by the generator function?
Additionally. The functions parameter is always size_t. There is also a redundancy and it is also not very flexible. The type of "ManyIndices" and the function parameter are always the same. So, no need to write that double.
Regarding flexibility. If I want to use a generator function with a different parameter data type, say, unsigned long long as in
constexpr unsigned long long factorial(unsigned long long n) noexcept {
return n == 0ull ? 1ull : n * factorial(n - 1ull);
}
I cannot do that. So, basically everything should be deduced from the generators functions signature.
This is also valid for the lines like
constexpr auto Factorial = generateArray<unsigned long long, getFactorial>(std::make_integer_sequence<size_t, ArraySize>());
Here, size_t is also the type of the parameter of the given function.
So, how eliminate redundancy and add flexibility?
DataType can be deduced from passed generator, use std::declval.
std::integer_sequence can be replaced by std::index_sequence.
Size for calculation must be provided explicitly.
template <typename GEN, size_t ... Indices>
constexpr auto generateArray2Helper(GEN gen, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<GEN>()(size_t{})), sizeof...(Indices)>{ gen(Indices)... };
}
template <size_t N, typename GEN>
constexpr auto generateArray2(GEN gen) {
return generateArray2Helper(gen, std::make_index_sequence<N>());
}
// The arrays ---------------------------------------------------------------------------
constexpr auto TriangleNumber = generateArray2<ArraySize>(getTriangleNumber);
constexpr auto FibonacciNumber = generateArray2<ArraySize>(getFibonacciNumber);
constexpr auto Factorial = generateArray2<ArraySize>(getFactorial);
Demo
c++20 version:
template<std::size_t...Is>
constexpr auto index_over(auto f, std::index_sequence<Is...>){
return f(std::integral_constant<std::size_t,Is>{}...);
}
template<auto N>
constexpr auto index_upto(auto f){
return index_over(f, std::make_index_sequence<N>{});
}
template<auto size>
constexpr auto gen_array(auto f){
return index_upto<size>([&](auto...Is){
return std::array{f(Is)...};
});
}
Suppose I have 3 bool type values
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
I would like to set a bitset denoting the three
std::bitset<3> foo;
How can I construct a bitset using the boolean values?
I want to do something like this
std::bitset<3> foo(canWalk,cantalk,caneat); //giving me 100
Following the example of Shivendra Agarwal, but using the constructor that receive an unsigned long long, I propose the following variadic template function (to be more generic)
template <typename ... Args>
unsigned long long getULL (Args ... as)
{
using unused = int[];
unsigned long long ret { 0ULL };
(void) unused { 0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)... };
return ret;
}
that permit the initialization of foo as follows
std::bitset<3> foo{ getULL(canwalk, cantalk, caneat) };
This works only if the dimension of the std::bitset isn't grater of the number of bits in an unsigned long long (with 3 whe are surely safe).
The following is a full working example
#include <bitset>
#include <iostream>
template <typename ... Args>
unsigned long long getULL (Args ... as)
{
using unused = int[];
unsigned long long ret { 0ULL };
(void) unused { 0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)... };
return ret;
}
int main()
{
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
std::bitset<3> foo{ getULL(canwalk, cantalk, caneat) };
std::cout << foo << std::endl;
}
IMHO, an initialization of type
std::bitset<3> foo(canWalk, cantalk, caneat);
is dangerous (error prone) because require that the template argument of std::bitset (3, in the example) correspond to the number of argument of the initialization.
I propose the creation of a "make" function (following the consolidated example of std::pair(), std::tuple(), std::make_unique(), std::make_shared) where the type and the number of arguments fix the returned type.
So I propose the following makeBitSet() function that return a std::bitset<N> where N is the number of the arguments
template <typename ... Args>
std::bitset<sizeof...(Args)> makeBitSet (Args ... as)
{
using unused = bool[];
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
(void) unused { true, (ret.set(--ui, as), true)... };
return ret;
}
The function can be used as follows
std::bitset<3> foo{ makeBitSet(canwalk, cantalk, caneat) };
but also (better, IMHO), using the C++11 auto,
auto foo = makeBitSet(canwalk, cantalk, caneat);
Observe that, starting from C++14, makeBitSet() can use the returning auto type
template <typename ... Args>
auto makeBitSet (Args ... as)
{
// ...
avoiding the annoying std::bitset<sizeof...(Args)> redundancy.
Moreover, starting from C++17, you can use template folding and, throwing away the unused array (and the corresponding using declaration), the makeBitSet() can be simplified as [EDIT: modified, to improve performances, following a suggestion from Mooing Duck (thanks!)]
template <typename ... Args>
auto makeBitSet (Args ... as)
{
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
( ret.set(--ui, as), ... );
return ret;
}
The following is a full working C++11 example
#include <bitset>
#include <iostream>
template <typename ... Args>
std::bitset<sizeof...(Args)> makeBitSet (Args ... as)
{
using unused = bool[];
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
(void) unused { true, (ret.set(--ui, as), true)... };
return ret;
}
int main()
{
bool canwalk { true };
bool cantalk { false };
bool caneat { false };
auto foo = makeBitSet(canwalk, cantalk, caneat);
std::cout << foo << std::endl;
}
Introduce a new api that can give you string input that bitset accepts in parameter.
to be more generic, recommendation will be to use bool array or [std::vector<bool>][1] to get rid of these variable parameters in getString()
inline std::string getString(bool canwalk, bool canTalk, bool canEat)
{
std::stringstream input;
str << canwalk?1:0 << cantalk?1:0 << caneat?1:0;
return input.str();
}
now can define bitset as:
std::bitset<3> foo (getString(canwalk, canTalk, canEat));
You basically need a builder that will build an initial value from your boolean set to pass to the constructor of std::bitset. You can do this at compile time (as opposed to runtime) via variadic templates, like so:
template <unsigned long long initialValue>
constexpr unsigned long long bitset_value_builder_impl() { return initialValue; }
template <unsigned long long initialValue, typename First, typename ... Args>
constexpr unsigned long long bitset_value_builder_impl(First &&first, Args &&...args) {
return first ?
bitset_value_builder_impl< (initialValue | (1UL<<sizeof...(args)) ), Args...>(std::forward<Args>(args)...) :
bitset_value_builder_impl< (initialValue & ~(1UL<<sizeof...(args)) ), Args...>(std::forward<Args>(args)...);
}
template <typename First, typename ... Args>
constexpr unsigned long long bitset_value_builder(First &&first, Args &&...args) {
return bitset_value_builder_impl<0, First, Args...>(std::forward<First>(first), std::forward<Args>(args)...);
}
int main()
{
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
std::bitset<3> bits{bitset_value_builder(canwalk, cantalk, caneat)};
std::cout << bits << std::endl; //100
}
Is it possible to declare a const array (possibly constexpr) at one point, then define it at another place, one element at a time?
E.g.
extern constexpr int myArray[100];
myArray[0] = myConstexprFunction(0);
myArray[1] = myConstexprFunction(1);
// ...
myArray[100] = myConstexprFunction(100);
What I'm trying to do will need something like this. Maybe it's possible using things like: http://b.atch.se/posts/constexpr-counter/
But if this technique is going to be illegal in the next C++ standard (I hope not) I would like to use a safer one.
[EDIT] how about relaxing some requirements.. let's say that I want to do something like this:
constexpr int myConstExprFunction(int arg) { return arg + 100;}
// other code...
constexpr int a = myConstExprFunctionBegin(10);
constexpr int b = myConstExprFunction(20);
constexpr int c = myConstExprFunction(30);
constexpr int d = myConstExprFunctionEnd(40);
what I would like to have is that the myConstExprFunctionEnd is able to generate a final array with the values created by the previous functions.
Everything at compile time of course.
[EDIT2] C++11 solutions very welcomed
The requirement of constexpr of the recent C++ is very relaxed, so you could just write:
// requires C++17:
constexpr auto myArray = [] {
std::array<int, 100> result {};
for (size_t i = 0; i < 100; ++ i) {
result[i] = i * i;
}
return result;
}();
Note I used std::array<int, 100> instead of int[100] because a function cannot return a C array.
The above code requires C++17 for two reasons:
constexpr lambda
The mutable operator[] is not constexpr before C++17
Issue 1 can be easily worked-around using a separate constexpr function. Issue 2 can only be solved by defining your own array wrapper.
// requires C++14:
template <typename T, size_t n>
struct ConstexprArray {
T data[n];
constexpr ConstexprArray() : data{} {}
constexpr T& operator[](size_t i) { return data[i]; }
};
constexpr auto initialize_my_array() -> ConstexprArray<int, 100> {
ConstexprArray<int, 100> result {};
for (size_t i = 0; i < 100; ++ i) {
result[i] = i * i;
}
return result;
}
constexpr auto myArray = initialize_my_array();
Looking at your edit, I'd just answer no, because the compiler cannot transform a group of variables into an array. It just don't work that way. There isn't any construct in C++ that can take a bunch of declaration, delete them and replace it with another declaration. A source code preprocessor or generator might be able to permit the syntax you seek.
If you're interested in a solution that doesn't require external tooling, you can create a constexpr function that returns an array:
constexpr auto makeMyArray() {
std::array<int, 100> myArray{};
myArray[0] = myConstExprFunction(10);
myArray[1] = myConstExprFunction(20);
// ...
return myArray;
}
Then, initialize your array:
constexpr auto myArray = makeMyArray();
constexpr declares that it is possible to evaluate the value of the function or variable at compile time.
So the only way you could use it with array is like:
constexpr int myArray[100]{1 , 2 , 3 ,.........};
statements like
myArray[0] = myConstexprFunction(0);
can only be evaluated during runtime. So its not possible.
If you want to declare constexpr an array and initialize it's value using a constexpr function... the best I can think is wrap the array in a struct/array and initialize it via a delegate constructor.
The following is a full working C++14 example
#include <utility>
#include <iostream>
constexpr int myConstexprFunction (int i)
{ return i << 1; } // return 2*i
template <std::size_t S>
struct wrapArray
{
int const myWrappedArray[S];
template <int ... Is>
constexpr wrapArray (std::integer_sequence<int, Is...> const &)
: myWrappedArray { myConstexprFunction(Is)... }
{ }
constexpr wrapArray ()
: wrapArray(std::make_integer_sequence<int, S>())
{ }
};
int main ()
{
constexpr wrapArray<100> wa100;
for ( auto i : wa100.myWrappedArray )
std::cout << i << ", ";
std::cout << std::endl;
}
If you need a C++11 code, you have to implement a substitute for std::integer_sequence and for std::make_integer_sequence(). It's not difficult.
No.
constexpr variables must be "immediately initialised".
Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}
Lets say that you have a function which generates some security token for your application, such as some hash salt, or maybe a symetric or asymetric key.
Now lets say that you have this function in your C++ as a constexpr and that you generate keys for your build based on some information (like, the build number, a timestamp, something else).
You being a diligent programmer make sure and call this in the appropriate ways to ensure it's only called at compile time, and thus the dead stripper removes the code from the final executable.
However, you can't ever be sure that someone else isn't going to call it in an unsafe way, or that maybe the compiler won't strip the function out, and then your security token algorithm will become public knowledge, making it more easy for would be attackers to guess future tokens.
Or, security aside, let's say the function takes a long time to execute and you want to make sure it never happens during runtime and causes a bad user experience for your end users.
Are there any ways to ensure that a constexpr function can never be called at runtime? Or alternately, throwing an assert or similar at runtime would be ok, but not as ideal obviously as a compile error would be.
I've heard that there is some way involving throwing an exception type that doesn't exist, so that if the constexpr function is not deadstripped out, you'll get a linker error, but have heard that this only works on some compilers.
Distantly related question: Force constexpr to be evaluated at compile time
In C++20 you can just replace constexpr by consteval to enforce a function to be always evaluated at compile time.
Example:
int rt_function(int v){ return v; }
constexpr int rt_ct_function(int v){ return v; }
consteval int ct_function(int v){ return v; }
int main(){
constexpr int ct_value = 1; // compile value
int rt_value = 2; // runtime value
int a = rt_function(ct_value);
int b = rt_ct_function(ct_value);
int c = ct_function(ct_value);
int d = rt_function(rt_value);
int e = rt_ct_function(rt_value);
int f = ct_function(rt_value); // ERROR: runtime value
constexpr int g = rt_function(ct_value); // ERROR: runtime function
constexpr int h = rt_ct_function(ct_value);
constexpr int i = ct_function(ct_value);
}
Pre C++20 workaround
You can enforce the use of it in a constant expression:
#include<utility>
template<typename T, T V>
constexpr auto ct() { return V; }
template<typename T>
constexpr auto func() {
return ct<decltype(std::declval<T>().value()), T{}.value()>();
}
template<typename T>
struct S {
constexpr S() {}
constexpr T value() { return T{}; }
};
template<typename T>
struct U {
U() {}
T value() { return T{}; }
};
int main() {
func<S<int>>();
// won't work
//func<U<int>>();
}
By using the result of the function as a template argument, you got an error if it can't be solved at compile-time.
A theoretical solution (as templates should be Turing complete) - don't use constexpr functions and fall back onto the good-old std=c++0x style of computing using exclusively struct template with values. For example, don't do
constexpr uintmax_t fact(uint n) {
return n>1 ? n*fact(n-1) : (n==1 ? 1 : 0);
}
but
template <uint N> struct fact {
uintmax_t value=N*fact<N-1>::value;
}
template <> struct fact<1>
uintmax_t value=1;
}
template <> struct fact<0>
uintmax_t value=0;
}
The struct approach is guaranteed to be evaluated exclusively at compile time.
The fact the guys at boost managed to do a compile time parser is a strong signal that, albeit tedious, this approach should be feasible - it's a one-off cost, maybe one can consider it an investment.
For example:
to power struct:
// ***Warning: note the unusual order of (power, base) for the parameters
// *** due to the default val for the base
template <unsigned long exponent, std::uintmax_t base=10>
struct pow_struct
{
private:
static constexpr uintmax_t at_half_pow=pow_struct<exponent / 2, base>::value;
public:
static constexpr uintmax_t value=
at_half_pow*at_half_pow*(exponent % 2 ? base : 1)
;
};
// not necessary, but will cut the recursion one step
template <std::uintmax_t base>
struct pow_struct<1, base>
{
static constexpr uintmax_t value=base;
};
template <std::uintmax_t base>
struct pow_struct<0,base>
{
static constexpr uintmax_t value=1;
};
The build token
template <uint vmajor, uint vminor, uint build>
struct build_token {
constexpr uintmax_t value=
vmajor*pow_struct<9>::value
+ vminor*pow_struct<6>::value
+ build_number
;
}
In the upcoming C++20 there will be consteval specifier.
consteval - specifies that a function is an immediate function, that is, every call to the function must produce a compile-time constant
Since now we have C++17, there is an easier solution:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
The key is that non-type arguments can be declared as auto. If you are using standards before C++17 you may have to use std::integral_constant. There is also a proposal about the constant helper class.
An example:
template <auto V>
struct constant {
constexpr static decltype(V) value = V;
};
constexpr uint64_t factorial(int n) {
if (n <= 0) {
return 1;
}
return n * factorial(n - 1);
}
int main() {
std::cout << "20! = " << constant<factorial(20)>::value << std::endl;
return 0;
}
Have your function take template parameters instead of arguments and implement your logic in a lambda.
#include <iostream>
template< uint64_t N >
constexpr uint64_t factorial() {
// note that we need to pass the lambda to itself to make the recursive call
auto f = []( uint64_t n, auto& f ) -> uint64_t {
if ( n < 2 ) return 1;
return n * f( n - 1, f );
};
return f( N, f );
}
using namespace std;
int main() {
cout << factorial<5>() << std::endl;
}