Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of constexpr function before definition fails

Tags:

c++

I'm having some trouble with constexpr. The book C++ Primer shows a line of code:

  constexpr int sz = size(); // only size() is a constexpr function                              // this code is right 

However the book doesn't give a specific example. So I try the following code by myself:

#include <iostream> constexpr int fun(); int main() {     constexpr int f = fun();     std::cout << f << std::endl; } constexpr int fun() {     return 3; } 

But my compiler said fun() is undefined.

If I change constexpr into const, it works well, and if I change my code to define the constexpr function before use:

#include <iostream> constexpr int fun() {     return 3; } int main() {     constexpr int f = fun();     std::cout << f << std::endl; } 

It also works well. Can someone tell me why?

like image 621
icecity96 Avatar asked Apr 03 '15 15:04

icecity96


People also ask

What is the point of constexpr functions?

constexpr functions A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.

Why constexpr instead of define?

#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.

Should I use constexpr everywhere?

Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.

Is constexpr always evaluated at compile time?

constexpr functions will be evaluated at compile time when all its arguments are constant expressions and the result is used in a constant expression as well.


1 Answers

A constexpr function does NOT have to be defined before its first use, however the result of any call made prior to definition is not a constant expression.

Source: C++ Standard draft n4296, section 5.20:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

  • this, except in a constexpr function or a constexpr constructor that is being evaluated as part of e;
  • an invocation of a function other than a constexpr constructor for a literal class, a constexpr function, or an implicit invocation of a trivial destructor [ Note: Overload resolution is applied as usual — end note ];
  • an invocation of an undefined constexpr function or an undefined constexpr constructor;
  • ...

version from draft 3485 (section 5.19):

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression, but subexpressions of logical AND, logical OR, and conditional operations that are not evaluated are not considered [ Note: An overloaded operator invokes a function. — end note ]:

  • this [ Note: when evaluating a constant expression, function invocation substitution replaces each occurrence of this in a constexpr member function with a pointer to the class object. — end note ];
  • an invocation of a function other than a constexpr constructor for a literal class or a constexpr function [ Note: Overload resolution is applied as usual — end note ];
  • an invocation of an undefined constexpr function or an undefined constexpr constructor
  • ...

The example int x2 = s. t(); in n2235 actually became valid due to the changes made prior to Standardization. However, constexpr int x2 = s. t(); remains an error.

like image 121
Ben Voigt Avatar answered Sep 20 '22 06:09

Ben Voigt