У меня есть код C++20/23 :
#include <cstddef>
template <size_t N>
class Foo {
public:
consteval size_t size() noexcept { return N; }
size_t real_size() {
return size() - 1;
}
};
int main(int argc, char* argv[]) {
Foo<5> foo;
return foo.real_size();
}
clang 10 и gcc 14.1 могут скомпилировать его без каких-либо ошибок/предупреждений.
Однако clang 14-18.1 выдает ошибку:
<source>:9:20: error: call to consteval function 'Foo<5>::size' is not a constant expression
9 | return size() - 1;
| ^
<source>:15:16: note: in instantiation of member function 'Foo<5>::real_size' requested here
15 | return foo.real_size();
| ^
<source>:9:20: note: implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function
9 | return size() - 1;
| ^
1 error generated.
Какие компиляторы соответствуют стандартам C++20 и C++23? Почему?
Это еще один пример P2280, который clang еще не реализован.
Исходное требование C++20 для основных константных выражений заключалось в том, что вам не разрешалось выполнять вычисления (из C++20 [expr.const]):
this
, за исключением функции constexpr или конструктора constexpr, который оценивается как часть e;
Который был изменен на (C++23 [expr.const]):
this
([expr.prim.this]), за исключением
- в функции constexpr ([dcl.constexpr]), которая оценивается как часть E или
- при появлении в качестве постфиксного выражения неявного или явного выражения доступа к члену класса ([expr.ref]);
Вызов size()
(который неявно является this->size()
, поскольку это нестатическая функция-член) должен быть постоянным выражением (потому что это consteval
). Это исходное правило отвергло оценку this
, но новое больше не делает этого. Таким образом, выражение this->size()
удовлетворяет правилам основного константного выражения.
Но this
— это не постоянное выражение, верно? Не в функции, отличной от constexpr
.
@NicolBolas Да, именно поэтому изначально оно было отклонено.
возможно, «вам не разрешалось вычислять [...] это, если только [...]» -> «как часть основного константного выражения вам не разрешалось…»
@Barry C++23 позволяет это, потому что this->some_member(_function)
считается postfix-expression
? И такой postfix-expression
«неявно» обращается к члену класса (Нет? думал, что член класса относится к статической переменной-члену в классе, нет?)
похоже, что class member
здесь относится к любой статической и нестатической переменной-члену и функции-члену? по сути, это означает, что любая неявная или явная this->
или obj.
, за которой следует consteval
функция-член (или функция класса), считается core constant expression
?
@463035818_is_not_an_ai Спасибо, сделал что-то подобное
Скомпилируйте с помощью
static
Demo.