Narek
Narek

Reputation: 39881

Any reason to declare constexpr for a function that returns void?

Here is what I read: using alias for static member functions?

In the answer I see a suggestion to use constexpr. What is the reason to use constexpr for void functions.

Please demonstrate a simple use case. I am new to constexpr so in complex examples I will not understand the gist.

Upvotes: 8

Views: 1984

Answers (4)

hermannk
hermannk

Reputation: 785

A reasonable use case is the manipulation of volatile variables. The following is a very simplified case from embedded programming using GNU tools (g++, ld):

To make an address of a peripheral a constexpr, you need to put it at a fixed location. This must be done in a linker script:

⋮
/* Define output sections */
SECTIONS
{
GPIO    0x48000000 (NOLOAD) : { *(.GPIO) }
⋮

Now, the .GPIO section is at the fixed address 0x48000400. Peripherals can be modeled by PODs containing volatile members. In the following example, the POD is named gpio_t and has just a single member: mode. The member can be set up in a constexpr function. Of course, there is no benefit to use a function to set a variable to a constant value. But in real use cases values and addresses have to be calculated. Think, e.g., of setting a divider for a Baud rate.

struct gpio_t {
    volatile std::uint32_t mode;
   };

__attribute__ ((section (".GPIO"))) gpio_t Gpio = {0};

static constexpr gpio_t *port {&Gpio};

static constexpr void init () {
    port->mode = 42u;
   };

void main {
    init ();
    ⋮
};

Note: The C-style idiom of casting integers to addresses does not work because it reinterpret_cast<> does not qualify for creating constexpr pointers (see Since C++14 illegal). The following fails:

constexpr gpio_t *port {(gpio_t *) 0x48000400};

Upvotes: 2

Jens
Jens

Reputation: 9416

Rahul's answer cites the standard paragraph which allow void constexpr functions, but it doesn't give a use-case. One use-case that comes to my mind would be to have a constexpr class, and as usual factor out behavior common to method in helper methods. The standard explicitly mentions function doing checks, e.g. assertions. I don't have a concrete example at hand, but I can imagine something like

class A
{
public:
    constexpr X doSomething(Y arg1) {
        checkInvariant();
        constraintOnYArgument(arg1);
        // ...
        checkInvariant();        
    }

    constexpr X doSomethingElse(Y arg1) {
        checkInvariant();
        constraintOnYArgument(arg1);
        // ...
        checkInvariant();        
    }

private:
    constexpr void constraintOnYArguments(Y arg) {
    }

    constexpr void checkInvariant() {
        // some checks
        if (!some condition) {
            throw std::logic_error("Oh no!");
        }
    }
};

Upvotes: 6

Rahul Tripathi
Rahul Tripathi

Reputation: 172578

As per the C++ 14 standard, void is a literal type

A type is a literal type if it is:

— void; or

— a scalar type; or

— a reference type; or

— an array of literal type; or

— a class type (Clause 9) that has all of the following properties: — it has a trivial destructor,

— it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and

— all of its non-static data members and base classes are of non-volatile literal types.

From here:

An arbitrary expression-statement is permitted, in order to allow calls to functions performing checks and to allow assert-like constructs. void also becomes a literal type, so that constexpr functions which exist only to perform such checks may return void.

Upvotes: 2

Patric Diran
Patric Diran

Reputation: 1

As long as parameter number is an integral constant, this constexpr version will compute the result at compile-time (C++11 compilers only). And when the number is a run-time integer, this same function is perfectly capable of computing the result at run-time. So you don't need two different versions of the same program: one for compile-time and another for run-time. One implementation does it all.

Upvotes: 0

Related Questions