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.
source to share
If you consider this statement in [dcl.constexpr] / 7:
Call function
constexpr
gives the same result as calling the equivalent functionconstexpr
in all respects , except that the function callconstexpr
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 functionconstexpr
or constructorconstexpr
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.
source to share
-
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 omitconstexpr
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 objectconstexpr
,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.
source to share