I think it's not possible but I'd like to ask you before give up about it.
I want something like a constexpr increment.
#include <iostream>
constexpr int inc() {
static int inc = 0;
return inc++;
}
class Foo {
static const int Type = inc();
};
class Foo2 {
static const int Type = inc();
};
int main() {
std::cout << "Foo1 " << Foo1::Type << st::endl;
std::cout << "Foo2 " << Foo2::Type << st::endl;
return 0;
}
I want to call it into some classes not manually (I use CRTP for that), to give a different type to each of them, but the type need to be const. There is anyway to achieve something like that in C++? (C++17 + TS)
constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.
for example, constexpr in front of function will tell the compiler to evaluate this function at compile-time instead of at the run time, hence it will improve the performance, It is like before the execution of your program the “ const int x ” will have the value 30
While this approach won’t apply constexpr in every case possible, it can safely apply it automatically. Benchmark your tests before and after running constexpr-everything. Not only will your code be faster and smaller, it’ll be safer. Code marked constexpr can’t bitrot as easily.
static constexpr int const& x = 42; // constexpr reference to a const int object // (the object has static storage duration // due to life extension by a static reference) Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.
So there is the solution by Filip Roseen called the constant-expression counter:
#include <iostream>
template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
};
template<int N>
struct writer {
friend constexpr int adl_flag (flag<N>) {
return N;
}
static constexpr int value = N;
};
template<int N, int = adl_flag (flag<N> {})>
int constexpr reader (int, flag<N>) {
return N;
}
template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1> {})) {
return R;
}
int constexpr reader (float, flag<0>) {
return 0;
}
template<int N = 1>
int constexpr next (int R = writer<reader (0, flag<32> {}) + N>::value) {
return R;
}
class Foo {
public:
static const int Type = next();
};
class Foo2 {
public:
static const int Type = next();
};
int main() {
std::cout << "Foo1 " << Foo::Type << std::endl;
std::cout << "Foo2 " << Foo2::Type << std::endl;
return 0;
}
Thanks guys :) But it's too risky for use it in my main library which will be use in every project.
PS: I won't close this right now if there is another answer. Because yes it's ugly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With