Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ constexpr auto member function. Clang issue?

 #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 code above will not compile in trunk Clang. The error is in the one() member function, 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 marked constexpr, and if you comment out the one() member, everything compiles fine, so we are clearly able to create the integral_constant from the ex, but not directly from the struct? It seems like, when I need the auto return type deduction, it fails and claims the function is not constexpr?

Is this expected? I feel like it should not be a problem, and I would be surprised if this was expected behavior.

like image 729
pat Avatar asked Mar 17 '23 03:03

pat


1 Answers

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

A call to a constexpr function produces the same result as a call to an equivalent non-constexpr function in all respects except that a call to a constexpr function can appear in a constant expression.

Consider the non-constexpr equivalent function A::one(). _data[a] cannot be used in a constant expression (as a non-type template argument) because it would involve the evaluation of this, from [expr.const]:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:
(2.1) — this (5.1.1), except in a constexpr function or a constexpr constructor that is being evaluated as part of e;

Since the non-constexpr equivalent is ill-formed, it is reasonable that the constexpr function give the same result.

Ont the other hand, two() is a well-formed member function regardless of constexpr and your use of ex.two(3) is valid as a constant expression - that's why it compiles.

like image 64
Barry Avatar answered Mar 24 '23 10:03

Barry