4

What are the general tips to convert a code to be a constexpr? Say, there is an algorithm for some geometrical transormation of (input) geometrical figure. Input and output differs by nature and size and depends from each other non-trivially. Currently it implemented as a class, which currently uses std::map and std::vector (without loss of generality).

What is a way to refactor code, that uses dynamic memory, to gain code, which matches the requirements for constant expressions?

I can imagine some combination of constexpr-compatible containers and constexpr-compatible implementation of "stack allocator" (for big enough storage) for each value_type of containers used. But there is a problem: I never met such a containers. But maybe there are another ways?

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • 1
    this is too general. – David Haim Jan 21 '16 at 13:55
  • @DavidHaim Where is a place for such general questions? I move the question to that place. Is there SO-like place? – Tomilov Anatoliy Jan 21 '16 at 13:55
  • Do you have something which *should* (or could) be a compile-time expression or value? Do you have a function which meets all the requirements for a [`constexpr` function](http://en.cppreference.com/w/cpp/language/constexpr)? Then you could make the expression, variable or function `constexpr`. And it doesn't hurt if you make something `constexpr` if that something really isn't or can't be a compile-time constant, it just implies `const` in that case. – Some programmer dude Jan 21 '16 at 13:59
  • @JoachimPileborg Currently don't, but want to. I don't use `reinterpret_cast`, placement `new` and other weird things. But I want to write a `constexpr` code, which is similar to its non-`constexpr` counterpart from a reader's point of view. I want to establish some kind of bijection. – Tomilov Anatoliy Jan 21 '16 at 14:04

1 Answers1

5

For most algorithms and utility classes (std::bitset, std::array, etc.) in the standard library, you can simply add the constexpr specifier everywhere and try and store the result in a constexpr variable. Most likely, this will compile and run successfully. See also this Q&A.

What will typically stop such code from compiling is one of the current language restrictions on compile-time constant expressions, such as (look at 5.20 Constant expressions [expr.const] for the full list)

  • dynamic memory allocation (inside std::inplace_merge e.g.)
  • virtual functions (in <iostream>)
  • lambda expressions (proposed and accepted for standardization in N4487)
  • reinterpret_cast
  • goto (proposed but rejected for standardization in N4472)

For each restriction, there are ways to get around it

  • The alternative to the system supported dynamic memory allocation through new/delete is to write your own memory pool in a large global constexpr array.
  • The alternative to virtual functions is to store an array of function pointers (that call constexpr functions) and dispatch them through a switch statement.
  • The alternative to lambdas is to write your own function objects with a constexpr operator().
  • The alternative to reinterpret_cast is to use a constexpr variant (with a union underneath it).
  • The alternative to goto is to write more structured code using regular loops and branches.

In all cases, you will lose the syntactic niceties of being able to call new/delete or implicit dynamic dispatching. You will have to manually allocate/deallocate your memory and to manually select your function pointer.

Note that even though large parts of the standard library could be made constexpr even with the current C++14/17 language, they currently are not. Moreover, standard library implementors are forbidden from adding extra constexpr functionality (in contrast from being allowed to offer stronger noexcept support).

Complain to your vendors or the C++ committee if you think there should be more or easier constexpr support (both in the language and the standard library).

Community
  • 1
  • 1
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • 1
    Alternative to `reinterpret_cast` from raw storage is to use `constexpr` variant (for example [this](https://github.com/eggs-cpp/variant)). – Tomilov Anatoliy Jan 21 '16 at 14:21