C ++ constexpr auto member function. Clan problem?

 #include <utility>

 struct A {
     constexpr auto one(int a) {
         return std::integral_constant<int, _data[a]>{};
     }
     constexpr int  two(int a) const {
         return _data[a];
     }

     int _data[10];
 };

 int main() {
     constexpr auto ex = A{{1,2,3,4,5,6,7,8,9,10}};

     std::integral_constant<int, ex.two(3)> b{};
 }

      

The above code will not compile into the Clang trunk. The error is in the member function one()

and says:

cc.cpp:57:44: note: implicit use of 'this' pointer is only allowed 
  within the evaluation of a call to a 'constexpr' member function.

      

Obviously the function is checked constexpr

, and if you comment out the member one()

everything compiles fine, so we can create integral_constant

from ex

, but not directly from struct

? It looks like when I need auto

return type inference it fails and asserts that the function is not constexpr

?

Is this expected? I feel like this shouldn't be a problem and I would be surprised if expected.

+3


source to share


2 answers


If you consider this statement in [dcl.constexpr] / 7:

Call function constexpr

gives the same result as calling the equivalent function constexpr

in all respects , except that the function call constexpr

can appear in constant terms.

Consider an equivalent function constexpr

constexpr

. _data[a]

cannot be used in a constant expression (as a non-type template argument), since it will include an evaluation this

, from [expr.const]:



A conditional expression e is a constant constant expression if evaluating e, following the rules of abstract machine (1.9), evaluates one of the following expressions:
(2.1) - this

(5.1.1), except for a function constexpr

or constructor constexpr

that evaluates to part of e;

Since the equivalent of non is constexpr

ill-formed, it constexpr

makes sense that the function would give the same result.

On the other hand, two()

is a well-formed member function whatever constexpr

, and your use ex.two(3)

is valid as a constant expression - that's why it compiles.

+6


source


  • constexpr

    functions are executed so that they can be called both at compile time and at run time.
  • The code with the function is constexpr

    well formed if you can omit constexpr

    and get the correct simple function. In other words, it should compile as a runtime function.
  • If the function body can constexpr

    not be evaluated at compile time, it still compiles, but you cannot use it in a temporary compilation context such as template arguments.
  • If the method constexpr

    is called on an object constexpr

    , this

    it is considered constexpr.

In case one

it is ill-formed because when it is compiled to run at runtime, _data[a]

it is considered a runtime expression because a

it is not a constant expression, even if this

and this->_data

.



In case two

it compiles just fine because it works great at runtime, and at compile time it this

is constexpr

as much as a

, so there this->_data[a]

is constexpr

and everything works fine.

+1


source







All Articles