camino
camino

Reputation: 10594

does all the functions inside a constexpr function in constexpr context must be constexpr function?

In ubuntu gcc 8.0:

void bar(){}

constexpr int foo(int a)
{
    if (a <=0 )
        bar();

    return 1;
}

int main()
{
    int a1[foo(-1)]; //will give a compile error, which is expected, 
                     //since non-constexpr function is not allowd in constexpr context
}

But in the following test:

int main()
{
    int a2[foo(1)];  //no compile error
}

Here, bar is non-constexpr function. I am wondering why non-constexpr function is allowed in constexpr context although in this test it doesn't get called.

Upvotes: 5

Views: 478

Answers (2)

Jans
Jans

Reputation: 11250

does all the functions inside a constexpr function in constexpr context must be constexpr function?

It depends.

The fact that calls to non-constexpr functions are allowed in constexpr functions doesn't mean that all possible calls to the constexpr function must result in a constant expression, but for context in which a constant expression is needed (like in array bounds), the call to the constexpr function must evaluate to a constant expression

The related parts of the standard for this case are:

[dcl.constexpr]/5

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (8.20), or, for a constructor, a constant initializer for some object (6.6.2), the program is ill-formed, no diagnostic required.

[expr.const]/2

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (4.6), would evaluate one of the following expressions:

  • (2.2) 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 [...]

This means that a constexpr function can have on its body calls to non-constexpr functions as long as there exist some arguments for which it evaluate to a constant expression or subexpression thereof, that's the reason why you can use foo(1) as value for the array bound, because it evaluation doesn't involve the call to bar() which is not the case for foo(-1).

Upvotes: 6

myhaspldeep
myhaspldeep

Reputation: 226

Use c++14 standard to compile your code:

$ 
$ g++ main.cpp -std=c++14
$ ./a.out
1
$ cat main.cpp
//
//  main.cpp
//
//
//  Created by myhaspl on 2018/10/24.
//  [email protected].
//

#include <iostream>
using namespace std;

void bar(){}

constexpr int foo(int a)
{
    if (a <=0 )
        bar();

    return 1;
}

int main()
{
    int a1[2]={0,1};

    cout<<a1[foo(-1)]<<endl;
}

Upvotes: -1

Related Questions