Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

member function that is not const should only be constexpr if on C++14 or later

In C++11, constexpr on a member function implies const. That was changed in C++14.

I have some code that has a member function that should be constexpr, but cannot be const, so I'd like it to be constexpr if compiled with std c++14 or later. One way to do this is:

class Foo {
#if _cplusplus >= 201402L
    constexpr
#endif
    int baz(const Bar& bar);
};

Is there a better way to express this, preferably without the preprocessor?

like image 491
Philipp Avatar asked Dec 16 '18 19:12

Philipp


People also ask

Should I use const or constexpr?

The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time. A constexpr variable must be initialized at compile time.

When to use #define vs constexpr?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

Does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later. So, what does constexpr mean?

Can constexpr use if?

constexpr if enables it to conditionally compile source code and can also be used for nice tricks at compile time.


1 Answers

The best way to do it would be to take advantage of the Feature-test Macros, as part of SD-6. The change that constexpr member functions are not implicitly const is marked as __cpp_constexpr having value 201304. So that should be your test:

class Foo {
#if __cpp_constexpr >= 201304L
    constexpr
#endif
    int baz(const Bar& bar);
};

Which if you do this for more than one member function, you probably want to generalize to:

#if __cpp_constexpr >= 201304L
#  define CONSTEXPR_MEM constexpr
#else
#  define CONSTEXPR_MEM
#endif

class Foo {
    CONSTEXPR_MEM int baz(const Bar& bar);
};

The way you present it in the question (using __cplusplus) is perfectly valid - the advantage of the feature-test macros is that different compiles adopt various features at different stages, so you can get a more granular, accurate test. Going forward, all the major vendors have agreed that SD-6 is the right direction and that will be the way to do things in the future.

Note that there is no way to express this without the preprocessor. There is no conditional constexpr. There is just constexpr.

like image 169
Barry Avatar answered Sep 23 '22 04:09

Barry