Understanding void constexpr-functions in c++14 [duplicate] - c++

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.

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!");
}
}
};

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.

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};

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.

Related

non-constexpr object usable in static_assert

I'll lead with the example
#include <array>
// Just in case std::array has superpowers...
template <typename T, unsigned n>
struct dummy {
constexpr unsigned size() const noexcept {
return n;
}
unsigned badsize() const noexcept {
return n;
}
};
void fun()
{
std::array<int, 8> arr{};
static_assert(arr.size() == 8); // OK
dummy<int, 8> arr2{};
static_assert(arr2.size() == 8); // OK
static_assert(arr2.badsize() == 8); // Compiler Error
}
The question is:
What is the language mechanism/rules that has allowed the non-const(expr) variables arr and arr2 to have their non-static but constexpr member functions size() be evaluated as a constant expression (bool-constexpr in particular)?
I've spent some time now searching SO and cppreference.com, but cannot work out why this is allowed.
I've recently had to update similar code to do static_assert(std::tuple_size_v<decltype(arr)> == 8) when upgrading from an older version of GCC, so I thought it was perhaps just some GCC extension at first. But I've now had this kind of code start working again with neweer versions of GCC, and I want to understand what's going on here.
There really isn’t any good reason this is allowed: it’s just that passing the address of the (non-constexpr) local variables as this to a member function is not considered in the rules for constant expressions. It’s even permitted to use this in the function called, but you can’t use any of the (non-static) member variables of the class unless they really were initialized as constants. Of course, these size functions don’t need to do so even if they aren’t actually static.
What’s really confusing is that this permission doesn’t extend to references: using them is considered a read of the effective pointer value, and that must separately be a constant. There are active proposals to allow such usage under the same inevitable restrictions on using the member variables of such an “unknown object”.

MSVC compiler fatal error C1001 using pointer to method

While writing a custom reflection library I encountered a strange compiler behavior. However I was able to reproduce the problem with a much simplified code. Here is:
#include <iostream>
class OtherBase{};
class Base{};
/* Used only as a test class to verify if the reflection API works properly*/
class Derived : Base, OtherBase
{
public:
void Printer()
{
std::cout << "Derived::Printer() has been called" << std::endl;
}
};
/*Descriptor class that basically incapsulate the address of Derived::Printer method*/
struct ClassDescriptor
{
using type = Derived;
struct FuncDescriptor
{
static constexpr const auto member_address{ &type::Printer };
};
};
int main()
{
Derived derived;
auto address{ &Derived::Printer };
(derived.*address)(); // -> OK it compiles fine using the local variable address
(derived.*ClassDescriptor::FuncDescriptor::member_address)(); // -> BROKEN using the address from the descriptor class cause fatal error C1001 !
}
While trying debugging this problem I noticed that:
It happen only if Derived has multiple inheritance.
If I swap static constexpr const auto member_address{ &type::Printer } with inline static const auto member_address{ &type::Printer } it works.
Is it just a compiler bug, or I'm doing something wrong ?
Can I solve this problem while keeping the constexpr ?
Please note that I'm using MSVC 2017 with the compiler version 19.16.27024.1
All compiler options are default except for /std:c++17 enabled.
I know that updating (and surely i'll do it) the compiler version to the last one will probably solve the issue, but for now I would like to understand more about this problem.
About C1001, Microsoft Developer Network suggests that you remove some optimizations in your code: Fatal Error C1001. Once you've worked out which optimization is causing the issue, you can use a #pragma to disable that optimization in just that area:
// Disable the optimization
#pragma optimize( "", off )
...
// Re-enable any previous optimization
#pragma optimize( "", on )
Also, a fix for this issue has been released by Microsoft. You could install the most recent release.
const and constexpr:
const declares an object as constant. This implies a guarantee that once initialized, the value of that object won't change, and the compiler can make use of this fact for optimizations. It also helps prevent the programmer from writing code that modifies objects that were not meant to be modified after initialization.
constexpr declares an object as fit for use in what the Standard calls constant expressions. But note that constexpr is not the only way to do this.
When applied to functions the basic difference is this:
const can only be used for non-static member functions, not functions in general. It gives a guarantee that the member function does not modify any of the non-static data members.
constexpr can be used with both member and non-member functions, as well as constructors. It declares the function fit for use in constant expressions. The compiler will only accept it if the function meets certain criteria (7.1.5/3,4), most importantly:
The function body must be non-virtual and extremely simple: Apart from typedefs and static asserts, only a single return statement is allowed. In the case of a constructor, only an initialization list, typedefs, and static assert are allowed. (= default and = delete are allowed, too, though.)
As of C++14, the rules are more relaxed, what is allowed since then inside a constexpr function: asm declaration, a goto statement, a statement with a label other than case and default, try-block, the definition of a variable of non-literal type, definition of a variable of static or thread storage duration, the definition of a variable for which no initialization is performed.
The arguments and the return type must be literal types (i.e., generally speaking, very simple types, typically scalars or aggregates)
When can I / should I use both, const and constexpr together?
A. In object declarations. This is never necessary when both keywords refer to the same object to be declared. constexpr implies const.
constexpr const int N = 5;
is the same as
constexpr int N = 5;
However, note that there may be situations when the keywords each refer to different parts of the declaration:
static constexpr int N = 3;
int main()
{
constexpr const int *NP = &N;
}
Here, NP is declared as an address constant-expression, i.e. a pointer that is itself a constant expression. (This is possible when the address is generated by applying the address operator to a static/global constant expression.) Here, both constexpr and const are required: constexpr always refers to the expression being declared (here NP), while const refers to int (it declares a pointer-to-const). Removing the const would render the expression illegal (because (a) a pointer to a non-const object cannot be a constant expression, and (b) &N is in-fact a pointer-to-constant).
B. In member function declarations. In C++11, constexpr implies const, while in C++14 and C++17 that is not the case. A member function declared under C++11 as
constexpr void f();
needs to be declared as
constexpr void f() const;
under C++14 in order to still be usable as a const function.
You could refer to this link for more details.

C++11 - Can't define constexpr literal using constexpr function?

I've run into what seems a counterintuitive error, namely, the inability to assign the value of a constexpr function to a constexpr literal (hope I'm using the language right). Here's the example:
class MyClass {
public:
static constexpr int FooValue(int n) { return n + 5; }
static constexpr int Foo5 = FooValue(5); // compiler error
static constexpr int Foo5Alt(void) { return FooValue(5); } // OK
};
In GCC 4.8.4, Foo5 is flagged for field initializer is not constant. Found this thread suggesting that the older version of GCC might be the culprit. So I plugged it into Coliru (GCC 6.2.0) and got the error 'static constexpr int MyClass::FooValue(int)' called in a constant expression before its definition is complete. I added Foo5Alt() which returns its value as a constexpr function rather than literal, and that compiles fine.
I guess I'm not following why FooValue(5) can't be used as the initializer for Foo5. The definition for FooValue(int n) is complete, isn't it? { return n + 5; } is the entire definition. constexpr denotes an expression that can be fully evaluated at compile time, so why can it not be used to define the return value of a constexpr literal?
What subtlety of C++ am I missing?
In C++, inline definitions of member functions for a class are only parsed after the declaration of the class is complete.
So even though the compiler "knows" about MyClass::FooValue(int), it hasn't "seen" its definition yet, and hence it can't be used in a constexpr expression.
A general workaround for this is to stick to constexpr member functions, or declare constexpr constants outside the class.
According to the standard, MyClass is considered an incomplete type when you try to invoke FooValue to initialize Foo5. Therefore, you cannot use its members as you did.
The type is considered a completely-defined object type (or complete type) at the closing }.
On the other side, the class is regarded as complete within function bodies. That's why Foo5Alt compiles just fine.
See [class.mem]/6 for further details.

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.
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!");
}
}
};
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.
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};
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.

When should literal classes be used in C++?

Can someone tell me when are literal classes needed in C++?
I am getting a little confused from constexpr constructors, constexpr members, and I can't see what the point is. I'd like to see some practical use of it.
Also I'd want to know if a set member function needs to be constexpr, i.e.:
constexpr void set_num(int a) { num = a; }
In C++03 this object has dynamic initialization
struct Data {
int i;
int j;
};
Data init_data(); // calculate something
const Data data = init_data();
i.e. when the program starts, before main runs, the function will be called and the object gets initialized.
In C++11 the object can have constant initialization, a form of static initialization, meaning that its value is set at compile-time and it's initialized before the program begins. This is useful to avoid the static initialization order fiasco among other things. To ensure the type gets constant initialization it must be initialized by a constant expression, so must have a constexpr constructor and any functions called in the full expression must be constexpr functions.
The type Data is trivial so its implicitly-declared constructors are constexpr constructors, so to make the global data undergo constant initialization we just need to make init_data() be a constexpr function:
struct Data {
int i;
int j;
};
constexpr Data init_data(); // calculate something
constexpr Data data = init_data();
The advantage of a literal type is that such types can be used in other constant expressions i.e. in contexts that require compile-time constants. So now that we have our data object as a compile-time constant, we can use it in other constant expressions e.g. to initialize other compile-time constants:
const int i = ::data.i;
And we can use the Data type for a static data member with an in-class initializer:
struct MoreData {
static constexpr Data zerozero = Data{}; // OK, Data is a literal type
};
If Data wasn't a literal type we would have to write:
struct MoreData {
static const Data zerozero;
};
// in moredata.cc
const Data MoreData::zerozero = Data{};
And then code which only sees the header doesn't know the value of MoreData::zerozero and can't use it in compile-time optimisations.
So the advantage of the "literal type" rules is that they allow you to define new class types that can be used in constant expressions. In C++03 only very few types, such as integers, could be used in constant expressions, e.g. integer literals such as 1 or 0x23 or compile-time constants of integer type. In C++11 you can write you own types which can have moderately complicated logic in their constructors (anything that can be expressed in a constexpr function) but can still be used as a compile-time constant.
Also I'd want to know if a set member function needs to be constexpr, i.e.
A constexpr member function is a special case of a const member function, so it can't modify (non-mutable) members of the type. A setter function, which modifies the object, can't be const.
To be a literal type a class must follow some rules including having at least one constexpr constructor. That doesn't mean all objects of that type must be constexpr constants, it just means that objects of that type can be constexpr constants if they are declared as such and are initialized using one of the class' constexpr constructors. To use the Data example again, most objects in your program would not be constants:
Data d = { 0, 1 };
d.i = d.i + 5;
So if you added a setter, a function which modifies the object, then it would only make sense to use it on non-const objects of that type, and like any other functions which modifies the type it should not be
constexpr fixes a problem in C++98 when using numeric limits. Before C++11 an expression such as
std::numeric_limits<short>::max()
can not be used as integral constant, although it is almost equal to macro INT_MAX. with C++11, such an expression is declared as constexpr so that, for example,
you can use it to declare arrays or in compile-time computations (metaprogramming):
std::array<float,std::numeric_limits<short>::max()> a;
A big advantage of constexpr classes is that they may be put into .ro data which can lead to executable size reductions and performance boosts. Esp. for geometric types e.g. or similar 'simple' types this is very neat as you could also get rid of "magic" numbers. See e.g. https://www.kdab.com/kdab-contributions-to-qt-5-0-part-4/.