Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constexpr tricks

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)

like image 566
Mathieu Van Nevel Avatar asked Dec 06 '16 10:12

Mathieu Van Nevel


People also ask

What is constexpr in C++?

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.

What is the use of constexpr in front of a function?

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

Is it safe to use constexpr-everything?

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.

What is constexpr int const&x = 42?

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.


1 Answers

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.

like image 116
Mathieu Van Nevel Avatar answered Oct 23 '22 19:10

Mathieu Van Nevel